Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
52067f67
Commit
52067f67
authored
Feb 19, 2009
by
The Android Open Source Project
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
auto import from //branches/cupcake/...@132276
parent
f83a870b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
312 additions
and
41 deletions
+312
-41
ProtoBuf.java
src/com/google/common/io/protocol/ProtoBuf.java
+114
-29
ProtoBufType.java
src/com/google/common/io/protocol/ProtoBufType.java
+48
-2
ProtoBufUtil.java
src/com/google/common/io/protocol/ProtoBufUtil.java
+150
-10
No files found.
src/com/google/common/io/protocol/ProtoBuf.java
View file @
52067f67
...
...
@@ -32,8 +32,8 @@ import java.util.*;
* but only the simple methods take default values into account. The reason for
* this behavior is that default values cannot be removed -- they would reappear
* after a serialization cycle. If a tag has repeated values, setXXX(tag, value)
* will overwrite all of them and getXXX(tag) will throw an exception.
*
* will overwrite all of them and getXXX(tag) will throw an exception.
*
*/
public
class
ProtoBuf
{
...
...
@@ -46,12 +46,12 @@ public class ProtoBuf {
private
static
final
String
MSG_UNSUPPORTED
=
"Unsupp.Type"
;
// names copied from //net/proto2/internal/wire_format.cc
private
static
final
int
WIRETYPE_END_GROUP
=
4
;
private
static
final
int
WIRETYPE_FIXED32
=
5
;
private
static
final
int
WIRETYPE_FIXED64
=
1
;
private
static
final
int
WIRETYPE_LENGTH_DELIMITED
=
2
;
private
static
final
int
WIRETYPE_START_GROUP
=
3
;
private
static
final
int
WIRETYPE_VARINT
=
0
;
static
final
int
WIRETYPE_END_GROUP
=
4
;
static
final
int
WIRETYPE_FIXED32
=
5
;
static
final
int
WIRETYPE_FIXED64
=
1
;
static
final
int
WIRETYPE_LENGTH_DELIMITED
=
2
;
static
final
int
WIRETYPE_START_GROUP
=
3
;
static
final
int
WIRETYPE_VARINT
=
0
;
/** Maximum number of bytes for VARINT wire format (64 bit, 7 bit/byte) */
private
static
final
int
VARINT_MAX_BYTES
=
10
;
...
...
@@ -62,7 +62,7 @@ public class ProtoBuf {
new
Long
(
10
),
new
Long
(
11
),
new
Long
(
12
),
new
Long
(
13
),
new
Long
(
14
),
new
Long
(
15
)};
private
final
ProtoBufType
msgType
;
private
ProtoBufType
msgType
;
private
final
Vector
values
=
new
Vector
();
/**
...
...
@@ -123,6 +123,20 @@ public class ProtoBuf {
insertLong
(
tag
,
getCount
(
tag
),
value
);
}
/**
* Appends the given (repeated) tag with the given float value.
*/
public
void
addFloat
(
int
tag
,
float
value
)
{
insertFloat
(
tag
,
getCount
(
tag
),
value
);
}
/**
* Appends the given (repeated) tag with the given double value.
*/
public
void
addDouble
(
int
tag
,
double
value
)
{
insertDouble
(
tag
,
getCount
(
tag
),
value
);
}
/**
* Appends the given (repeated) tag with the given group or message value.
*/
...
...
@@ -196,6 +210,34 @@ public class ProtoBuf {
return
((
Long
)
getObject
(
tag
,
index
,
ProtoBufType
.
TYPE_INT64
)).
longValue
();
}
/**
* Returns the float value for the given tag.
*/
public
float
getFloat
(
int
tag
)
{
return
Float
.
intBitsToFloat
(
getInt
(
tag
));
}
/**
* Returns the float value for the given repeated tag at the given index.
*/
public
float
getFloat
(
int
tag
,
int
index
)
{
return
Float
.
intBitsToFloat
(
getInt
(
tag
,
index
));
}
/**
* Returns the double value for the given tag.
*/
public
double
getDouble
(
int
tag
)
{
return
Double
.
longBitsToDouble
(
getLong
(
tag
));
}
/**
* Returns the double value for the given repeated tag at the given index.
*/
public
double
getDouble
(
int
tag
,
int
index
)
{
return
Double
.
longBitsToDouble
(
getLong
(
tag
,
index
));
}
/**
* Returns the group or nested message for the given tag.
*/
...
...
@@ -234,6 +276,20 @@ public class ProtoBuf {
return
msgType
;
}
/**
* Sets the type definition of this protocol buffer. Used internally in
* ProtoBufUtil for incremental reading.
*
* @param type the new type
*/
void
setType
(
ProtoBufType
type
)
{
if
(
values
.
size
()
!=
0
||
(
msgType
!=
null
&&
type
!=
null
&&
type
!=
msgType
))
{
throw
new
IllegalArgumentException
();
}
this
.
msgType
=
type
;
}
/**
* Convenience method for determining whether a tag has a value. Note: in
* contrast to getCount(tag) > 0, this method takes the default value
...
...
@@ -652,6 +708,20 @@ public class ProtoBuf {
?
SMALL_NUMBERS
[(
int
)
value
]
:
new
Long
(
value
));
}
/**
* Sets the given tag to the given double value.
*/
public
void
setDouble
(
int
tag
,
double
value
)
{
setLong
(
tag
,
Double
.
doubleToLongBits
(
value
));
}
/**
* Sets the given tag to the given float value.
*/
public
void
setFloat
(
int
tag
,
float
value
)
{
setInt
(
tag
,
Float
.
floatToIntBits
(
value
));
}
/**
* Sets the given tag to the given Group or nested Message.
*/
...
...
@@ -695,6 +765,20 @@ public class ProtoBuf {
?
SMALL_NUMBERS
[(
int
)
value
]
:
new
Long
(
value
));
}
/**
* Inserts the given float value for the given tag at the given index.
*/
public
void
insertFloat
(
int
tag
,
int
index
,
float
value
)
{
insertInt
(
tag
,
index
,
Float
.
floatToIntBits
(
value
));
}
/**
* Inserts the given double value for the given tag at the given index.
*/
public
void
insertDouble
(
int
tag
,
int
index
,
double
value
)
{
insertLong
(
tag
,
index
,
Double
.
doubleToLongBits
(
value
));
}
/**
* Inserts the given group or message for the given tag at the given index.
*/
...
...
@@ -739,6 +823,8 @@ public class ProtoBuf {
case
ProtoBufType
.
TYPE_UINT64
:
case
ProtoBufType
.
TYPE_SINT32
:
case
ProtoBufType
.
TYPE_SINT64
:
case
ProtoBufType
.
TYPE_FLOAT
:
case
ProtoBufType
.
TYPE_DOUBLE
:
return
;
}
}
else
if
(
object
instanceof
byte
[]){
...
...
@@ -748,7 +834,6 @@ public class ProtoBuf {
case
ProtoBufType
.
TYPE_MESSAGE
:
case
ProtoBufType
.
TYPE_TEXT
:
case
ProtoBufType
.
TYPE_BYTES
:
case
ProtoBufType
.
TYPE_STRING
:
return
;
}
}
else
if
(
object
instanceof
ProtoBuf
)
{
...
...
@@ -1079,21 +1164,21 @@ public class ProtoBuf {
/**
* Encodes the given string to UTF-8 in the given buffer or calculates
* the space needed if the buffer is null.
*
*
* @param s the string to be UTF-8 encoded
* @param buf byte array to write to
* @return new buffer position after writing (which equals the required size
* @return new buffer position after writing (which equals the required size
* if pos is 0)
*/
static
int
encodeUtf8
(
String
s
,
byte
[]
buf
,
int
pos
){
int
len
=
s
.
length
();
for
(
int
i
=
0
;
i
<
len
;
i
++){
int
code
=
s
.
charAt
(
i
);
// surrogate 0xd800 .. 0xdfff?
if
(
code
>=
0x0d800
&&
code
<=
0x0dfff
&&
i
+
1
<
len
){
int
codeLo
=
s
.
charAt
(
i
+
1
);
// 0xfc00 is the surrogate id mask (first six bit of 16 set)
// 0x03ff is the surrogate data mask (remaining 10 bit)
// check if actually a surrogate pair (d800 ^ dc00 == 0400)
...
...
@@ -1138,35 +1223,35 @@ public class ProtoBuf {
buf
[
pos
+
2
]
=
(
byte
)
((
0x80
|
((
code
>>
6
)
&
0x3F
)));
buf
[
pos
+
3
]
=
(
byte
)
((
0x80
|
(
code
&
0x3F
)));
}
pos
+=
4
;
pos
+=
4
;
}
}
return
pos
;
}
/**
* Decodes an array of UTF-8 bytes to a Java string (UTF-16). The tolerant
* flag determines what to do in case of illegal or unsupported sequences.
*
* @param data input byte array containing UTF-8 data
* Decodes an array of UTF-8 bytes to a Java string (UTF-16). The tolerant
* flag determines what to do in case of illegal or unsupported sequences.
*
* @param data input byte array containing UTF-8 data
* @param start decoding start position in byte array
* @param end decoding end position in byte array
* @param tolerant if true, an IllegalArgumentException is thrown for illegal
* @param tolerant if true, an IllegalArgumentException is thrown for illegal
* UTF-8 codes
* @return the string containing the UTF-8 decoding result
*/
static
String
decodeUtf8
(
byte
[]
data
,
int
start
,
int
end
,
static
String
decodeUtf8
(
byte
[]
data
,
int
start
,
int
end
,
boolean
tolerant
){
StringBuffer
sb
=
new
StringBuffer
(
end
-
start
);
int
pos
=
start
;
while
(
pos
<
end
){
int
b
=
data
[
pos
++]
&
0x0ff
;
if
(
b
<=
0x7f
){
sb
.
append
((
char
)
b
);
}
else
if
(
b
>=
0xf5
){
// byte sequence too long
}
else
if
(
b
>=
0xf5
){
// byte sequence too long
if
(!
tolerant
){
throw
new
IllegalArgumentException
(
"Invalid UTF8"
);
}
...
...
@@ -1174,16 +1259,16 @@ public class ProtoBuf {
}
else
{
int
border
=
0xe0
;
int
count
=
1
;
int
minCode
=
128
;
int
minCode
=
128
;
int
mask
=
0x01f
;
while
(
b
>=
border
){
border
=
(
border
>>
1
)
|
0x80
;
minCode
=
minCode
<<
(
count
==
1
?
4
:
5
);
minCode
=
minCode
<<
(
count
==
1
?
4
:
5
);
count
++;
mask
=
mask
>>
1
;
}
int
code
=
b
&
mask
;
for
(
int
i
=
0
;
i
<
count
;
i
++){
code
=
code
<<
6
;
if
(
pos
>=
end
){
...
...
@@ -1198,7 +1283,7 @@ public class ProtoBuf {
code
|=
(
data
[
pos
++]
&
0x3f
);
// six bit
}
}
// illegal code or surrogate code
if
(!
tolerant
&&
code
<
minCode
||
(
code
>=
0xd800
&&
code
<=
0xdfff
)){
throw
new
IllegalArgumentException
(
"Invalid UTF8"
);
...
...
src/com/google/common/io/protocol/ProtoBufType.java
View file @
52067f67
// Copyright 2007
The Android Open Source Project
// Copyright 2007
Google Inc.
// All Rights Reserved.
package
com
.
google
.
common
.
io
.
protocol
;
...
...
@@ -9,7 +9,6 @@ import java.util.*;
* This class can be used to create a memory model of a .proto file. Currently,
* it is assumed that tags ids are not large. This could be improved by storing
* a start offset, relaxing the assumption to a dense number space.
*
*/
public
class
ProtoBufType
{
// Note: Values 0..15 are reserved for wire types!
...
...
@@ -121,4 +120,51 @@ public class ProtoBufType {
public
String
toString
()
{
return
typeName
;
}
/**
* {@inheritDoc}
* <p>Two ProtoBufTypes are equals if the fields types are the same.
*/
public
boolean
equals
(
Object
object
)
{
if
(
null
==
object
)
{
// trivial check
return
false
;
}
else
if
(
this
==
object
)
{
// trivial check
return
true
;
}
else
if
(
this
.
getClass
()
!=
object
.
getClass
())
{
// different class
return
false
;
}
ProtoBufType
other
=
(
ProtoBufType
)
object
;
return
stringEquals
(
types
,
other
.
types
);
}
/**
* {@inheritDoc}
*/
public
int
hashCode
()
{
if
(
types
!=
null
)
{
return
types
.
hashCode
();
}
else
{
return
super
.
hashCode
();
}
}
public
static
boolean
stringEquals
(
CharSequence
a
,
CharSequence
b
)
{
if
(
a
==
b
)
return
true
;
int
length
;
if
(
a
!=
null
&&
b
!=
null
&&
(
length
=
a
.
length
())
==
b
.
length
())
{
if
(
a
instanceof
String
&&
b
instanceof
String
)
{
return
a
.
equals
(
b
);
}
else
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
if
(
a
.
charAt
(
i
)
!=
b
.
charAt
(
i
))
return
false
;
}
return
true
;
}
}
return
false
;
}
}
src/com/google/common/io/protocol/ProtoBufUtil.java
View file @
52067f67
// Copyright 2008
The Android Open Source Project
// Copyright 2008
Google Inc. All Rights Reserved.
package
com
.
google
.
common
.
io
.
protocol
;
import
java.io.*
;
/**
* Utility functions for dealing with ProtoBuf objects consolidated from
* previous spot implementations across the codebase.
...
...
@@ -24,14 +26,39 @@ public final class ProtoBufUtil {
public
static
String
getSubProtoValueOrEmpty
(
ProtoBuf
proto
,
int
sub
,
int
tag
)
{
try
{
ProtoBuf
subProto
=
(
proto
!=
null
&&
proto
.
has
(
sub
))
?
proto
.
getProtoBuf
(
sub
)
:
null
;
return
getProtoValueOrEmpty
(
subProto
,
tag
);
return
getProtoValueOrEmpty
(
getSubProtoOrNull
(
proto
,
sub
),
tag
);
}
catch
(
ClassCastException
e
)
{
return
""
;
}
}
/** Convenience method to get a subproto if the proto has it. */
public
static
ProtoBuf
getSubProtoOrNull
(
ProtoBuf
proto
,
int
sub
)
{
return
(
proto
!=
null
&&
proto
.
has
(
sub
))
?
proto
.
getProtoBuf
(
sub
)
:
null
;
}
/**
* Get an int with "tag" from the proto buffer. If the given field can't be
* retrieved, return the provided default value.
*
* @param proto The proto buffer.
* @param tag The tag value that identifies which protocol buffer field to
* retrieve.
* @param defaultValue The value to return if the field can't be retrieved.
* @return The result which should be an integer.
*/
public
static
int
getProtoValueOrDefault
(
ProtoBuf
proto
,
int
tag
,
int
defaultValue
)
{
try
{
return
(
proto
!=
null
&&
proto
.
has
(
tag
))
?
proto
.
getInt
(
tag
)
:
defaultValue
;
}
catch
(
IllegalArgumentException
e
)
{
return
defaultValue
;
}
catch
(
ClassCastException
e
)
{
return
defaultValue
;
}
}
/**
* Get an Int with "tag" from the proto buffer.
* If the given field can't be retrieved, return 0.
...
...
@@ -42,12 +69,25 @@ public final class ProtoBufUtil {
* @return The result which should be an integer.
*/
public
static
int
getProtoValueOrZero
(
ProtoBuf
proto
,
int
tag
)
{
return
getProtoValueOrDefault
(
proto
,
tag
,
0
);
}
/**
* Get an Long with "tag" from the proto buffer.
* If the given field can't be retrieved, return 0.
*
* @param proto The proto buffer.
* @param tag The tag value that identifies which protocol buffer field to
* retrieve.
* @return The result which should be an integer.
*/
public
static
long
getProtoLongValueOrZero
(
ProtoBuf
proto
,
int
tag
)
{
try
{
return
(
proto
!=
null
&&
proto
.
has
(
tag
))
?
proto
.
get
Int
(
tag
)
:
0
;
return
(
proto
!=
null
&&
proto
.
has
(
tag
))
?
proto
.
get
Long
(
tag
)
:
0L
;
}
catch
(
IllegalArgumentException
e
)
{
return
0
;
return
0
L
;
}
catch
(
ClassCastException
e
)
{
return
0
;
return
0
L
;
}
}
...
...
@@ -70,6 +110,39 @@ public final class ProtoBufUtil {
}
}
/**
* Reads a single protocol buffer from the given input stream. This method is
* provided where the client needs incremental access to the contents of a
* protocol buffer which contains a sequence of protocol buffers.
* <p />
* Please use {@link #getInputStreamForProtoBufResponse} to obtain an input
* stream suitable for this method.
*
* @param umbrellaType the type of the "outer" protocol buffer containing
* the message to read
* @param is the stream to read the protocol buffer from
* @param result the result protocol buffer (must be empty, will be filled
* with the data read and the type will be set)
* @return the tag id of the message, -1 at the end of the stream
*/
public
static
int
readNextProtoBuf
(
ProtoBufType
umbrellaType
,
InputStream
is
,
ProtoBuf
result
)
throws
IOException
{
long
tagAndType
=
ProtoBuf
.
readVarInt
(
is
,
true
/* permits EOF */
);
if
(
tagAndType
==
-
1
)
{
return
-
1
;
}
if
((
tagAndType
&
7
)
!=
ProtoBuf
.
WIRETYPE_LENGTH_DELIMITED
)
{
throw
new
IOException
(
"Message expected"
);
}
int
tag
=
(
int
)
(
tagAndType
>>>
3
);
result
.
setType
((
ProtoBufType
)
umbrellaType
.
getData
(
tag
));
int
length
=
(
int
)
ProtoBuf
.
readVarInt
(
is
,
false
);
result
.
parse
(
is
,
length
);
return
tag
;
}
/**
* A wrapper for <code> getProtoValueOrNegativeOne </code> that drills into
* a sub message returning the long value if it exists, returning -1 if it
...
...
@@ -85,13 +158,80 @@ public final class ProtoBufUtil {
public
static
long
getSubProtoValueOrNegativeOne
(
ProtoBuf
proto
,
int
sub
,
int
tag
)
{
try
{
ProtoBuf
subProto
=
(
proto
!=
null
&&
proto
.
has
(
sub
))
?
proto
.
getProtoBuf
(
sub
)
:
null
;
return
getProtoValueOrNegativeOne
(
subProto
,
tag
);
return
getProtoValueOrNegativeOne
(
getSubProtoOrNull
(
proto
,
sub
),
tag
);
}
catch
(
IllegalArgumentException
e
)
{
return
-
1
;
}
catch
(
ClassCastException
e
)
{
return
-
1
;
}
}
/**
* A wrapper for {@link #getProtoValueOrDefault(ProtoBuf, int, int)} that
* drills into a sub message returning the int value if it exists, returning
* the given default if it does not.
*
* @param proto The proto buffer.
* @param tag The tag value that identifies which protocol buffer field to
* retrieve.
* @param sub The sub tag value that identifies which protocol buffer
* sub-field to retrieve.
* @param defaultValue The value to return if the field is not present.
* @return The result which should be a long.
*/
public
static
int
getSubProtoValueOrDefault
(
ProtoBuf
proto
,
int
sub
,
int
tag
,
int
defaultValue
)
{
try
{
return
getProtoValueOrDefault
(
getSubProtoOrNull
(
proto
,
sub
),
tag
,
defaultValue
);
}
catch
(
IllegalArgumentException
e
)
{
return
defaultValue
;
}
catch
(
ClassCastException
e
)
{
return
defaultValue
;
}
}
/**
* Creates a sub ProtoBuf of the given Protobuf and sets it.
*
* @param proto The proto buffer.
* @param tag The tag value that identifies which protocol buffer field to
* create.
* @return the sub ProtoBuf generated.
*/
public
static
ProtoBuf
createProtoBuf
(
ProtoBuf
proto
,
int
tag
)
{
ProtoBuf
child
=
proto
.
createGroup
(
tag
);
proto
.
setProtoBuf
(
tag
,
child
);
return
child
;
}
/**
* Creates a sub ProtoBuf of the given Protobuf and adds it.
*
* @param proto The proto buffer.
* @param tag The tag value that identifies which protocol buffer field to
* add.
* @return the sub ProtoBuf generated.
*/
public
static
ProtoBuf
addProtoBuf
(
ProtoBuf
proto
,
int
tag
)
{
ProtoBuf
child
=
proto
.
createGroup
(
tag
);
proto
.
addProtoBuf
(
tag
,
child
);
return
child
;
}
/**
* Writes the ProtoBuf to the given DataOutput. This is useful for unit
* tests.
*
* @param output The data output to write to.
* @param protoBuf The proto buffer.
*/
public
static
void
writeProtoBufToOutput
(
DataOutput
output
,
ProtoBuf
protoBuf
)
throws
IOException
{
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
protoBuf
.
outputTo
(
baos
);
byte
[]
bytes
=
baos
.
toByteArray
();
output
.
writeInt
(
bytes
.
length
);
output
.
write
(
bytes
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment