|
|
@ -9,52 +9,22 @@ |
|
|
|
#define UPB_WIRE_READER_H_ |
|
|
|
#define UPB_WIRE_READER_H_ |
|
|
|
|
|
|
|
|
|
|
|
#include "upb/wire/eps_copy_input_stream.h" |
|
|
|
#include "upb/wire/eps_copy_input_stream.h" |
|
|
|
#include "upb/wire/internal/swap.h" |
|
|
|
#include "upb/wire/internal/endian.h" |
|
|
|
|
|
|
|
#include "upb/wire/internal/reader.h" |
|
|
|
#include "upb/wire/types.h" // IWYU pragma: export |
|
|
|
#include "upb/wire/types.h" // IWYU pragma: export |
|
|
|
|
|
|
|
|
|
|
|
// Must be last.
|
|
|
|
// Must be last.
|
|
|
|
#include "upb/port/def.inc" |
|
|
|
#include "upb/port/def.inc" |
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
|
|
|
|
|
extern "C" { |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The upb_WireReader interface is suitable for general-purpose parsing of
|
|
|
|
// The upb_WireReader interface is suitable for general-purpose parsing of
|
|
|
|
// protobuf binary wire format. It is designed to be used along with
|
|
|
|
// protobuf binary wire format. It is designed to be used along with
|
|
|
|
// upb_EpsCopyInputStream for buffering, and all parsing routines in this file
|
|
|
|
// upb_EpsCopyInputStream for buffering, and all parsing routines in this file
|
|
|
|
// assume that at least kUpb_EpsCopyInputStream_SlopBytes worth of data is
|
|
|
|
// assume that at least kUpb_EpsCopyInputStream_SlopBytes worth of data is
|
|
|
|
// available to read without any bounds checks.
|
|
|
|
// available to read without any bounds checks.
|
|
|
|
|
|
|
|
|
|
|
|
#define kUpb_WireReader_WireTypeMask 7 |
|
|
|
#ifdef __cplusplus |
|
|
|
#define kUpb_WireReader_WireTypeBits 3 |
|
|
|
extern "C" { |
|
|
|
|
|
|
|
#endif |
|
|
|
typedef struct { |
|
|
|
|
|
|
|
const char* ptr; |
|
|
|
|
|
|
|
uint64_t val; |
|
|
|
|
|
|
|
} _upb_WireReader_ReadLongVarintRet; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_upb_WireReader_ReadLongVarintRet _upb_WireReader_ReadLongVarint( |
|
|
|
|
|
|
|
const char* ptr, uint64_t val); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static UPB_FORCEINLINE const char* _upb_WireReader_ReadVarint(const char* ptr, |
|
|
|
|
|
|
|
uint64_t* val, |
|
|
|
|
|
|
|
int maxlen, |
|
|
|
|
|
|
|
uint64_t maxval) { |
|
|
|
|
|
|
|
uint64_t byte = (uint8_t)*ptr; |
|
|
|
|
|
|
|
if (UPB_LIKELY((byte & 0x80) == 0)) { |
|
|
|
|
|
|
|
*val = (uint32_t)byte; |
|
|
|
|
|
|
|
return ptr + 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
const char* start = ptr; |
|
|
|
|
|
|
|
_upb_WireReader_ReadLongVarintRet res = |
|
|
|
|
|
|
|
_upb_WireReader_ReadLongVarint(ptr, byte); |
|
|
|
|
|
|
|
if (!res.ptr || (maxlen < 10 && res.ptr - start > maxlen) || |
|
|
|
|
|
|
|
res.val > maxval) { |
|
|
|
|
|
|
|
return NULL; // Malformed.
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*val = res.val; |
|
|
|
|
|
|
|
return res.ptr; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Parses a tag into `tag`, and returns a pointer past the end of the tag, or
|
|
|
|
// Parses a tag into `tag`, and returns a pointer past the end of the tag, or
|
|
|
|
// NULL if there was an error in the tag data.
|
|
|
|
// NULL if there was an error in the tag data.
|
|
|
@ -65,7 +35,7 @@ static UPB_FORCEINLINE const char* _upb_WireReader_ReadVarint(const char* ptr, |
|
|
|
static UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr, |
|
|
|
static UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr, |
|
|
|
uint32_t* tag) { |
|
|
|
uint32_t* tag) { |
|
|
|
uint64_t val; |
|
|
|
uint64_t val; |
|
|
|
ptr = _upb_WireReader_ReadVarint(ptr, &val, 5, UINT32_MAX); |
|
|
|
ptr = UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, &val, 5, UINT32_MAX); |
|
|
|
if (!ptr) return NULL; |
|
|
|
if (!ptr) return NULL; |
|
|
|
*tag = val; |
|
|
|
*tag = val; |
|
|
|
return ptr; |
|
|
|
return ptr; |
|
|
@ -73,17 +43,17 @@ static UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr, |
|
|
|
|
|
|
|
|
|
|
|
// Given a tag, returns the field number.
|
|
|
|
// Given a tag, returns the field number.
|
|
|
|
UPB_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag) { |
|
|
|
UPB_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag) { |
|
|
|
return tag >> kUpb_WireReader_WireTypeBits; |
|
|
|
return UPB_PRIVATE(_upb_WireReader_GetFieldNumber)(tag); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Given a tag, returns the wire type.
|
|
|
|
// Given a tag, returns the wire type.
|
|
|
|
UPB_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag) { |
|
|
|
UPB_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag) { |
|
|
|
return tag & kUpb_WireReader_WireTypeMask; |
|
|
|
return UPB_PRIVATE(_upb_WireReader_GetWireType)(tag); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UPB_INLINE const char* upb_WireReader_ReadVarint(const char* ptr, |
|
|
|
UPB_INLINE const char* upb_WireReader_ReadVarint(const char* ptr, |
|
|
|
uint64_t* val) { |
|
|
|
uint64_t* val) { |
|
|
|
return _upb_WireReader_ReadVarint(ptr, val, 10, UINT64_MAX); |
|
|
|
return UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, val, 10, UINT64_MAX); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Skips data for a varint, returning a pointer past the end of the varint, or
|
|
|
|
// Skips data for a varint, returning a pointer past the end of the varint, or
|
|
|
@ -119,7 +89,7 @@ UPB_INLINE const char* upb_WireReader_ReadSize(const char* ptr, int* size) { |
|
|
|
UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) { |
|
|
|
UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) { |
|
|
|
uint32_t uval; |
|
|
|
uint32_t uval; |
|
|
|
memcpy(&uval, ptr, 4); |
|
|
|
memcpy(&uval, ptr, 4); |
|
|
|
uval = _upb_BigEndian_Swap32(uval); |
|
|
|
uval = UPB_PRIVATE(_upb_BigEndian32)(uval); |
|
|
|
memcpy(val, &uval, 4); |
|
|
|
memcpy(val, &uval, 4); |
|
|
|
return ptr + 4; |
|
|
|
return ptr + 4; |
|
|
|
} |
|
|
|
} |
|
|
@ -132,14 +102,14 @@ UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) { |
|
|
|
UPB_INLINE const char* upb_WireReader_ReadFixed64(const char* ptr, void* val) { |
|
|
|
UPB_INLINE const char* upb_WireReader_ReadFixed64(const char* ptr, void* val) { |
|
|
|
uint64_t uval; |
|
|
|
uint64_t uval; |
|
|
|
memcpy(&uval, ptr, 8); |
|
|
|
memcpy(&uval, ptr, 8); |
|
|
|
uval = _upb_BigEndian_Swap64(uval); |
|
|
|
uval = UPB_PRIVATE(_upb_BigEndian64)(uval); |
|
|
|
memcpy(val, &uval, 8); |
|
|
|
memcpy(val, &uval, 8); |
|
|
|
return ptr + 8; |
|
|
|
return ptr + 8; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char* _upb_WireReader_SkipGroup(const char* ptr, uint32_t tag, |
|
|
|
const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( |
|
|
|
int depth_limit, |
|
|
|
const char* ptr, uint32_t tag, int depth_limit, |
|
|
|
upb_EpsCopyInputStream* stream); |
|
|
|
upb_EpsCopyInputStream* stream); |
|
|
|
|
|
|
|
|
|
|
|
// Skips data for a group, returning a pointer past the end of the group, or
|
|
|
|
// Skips data for a group, returning a pointer past the end of the group, or
|
|
|
|
// NULL if there was an error parsing the group. The `tag` argument should be
|
|
|
|
// NULL if there was an error parsing the group. The `tag` argument should be
|
|
|
@ -152,7 +122,7 @@ const char* _upb_WireReader_SkipGroup(const char* ptr, uint32_t tag, |
|
|
|
// control over this?
|
|
|
|
// control over this?
|
|
|
|
UPB_INLINE const char* upb_WireReader_SkipGroup( |
|
|
|
UPB_INLINE const char* upb_WireReader_SkipGroup( |
|
|
|
const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { |
|
|
|
const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { |
|
|
|
return _upb_WireReader_SkipGroup(ptr, tag, 100, stream); |
|
|
|
return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, 100, stream); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UPB_INLINE const char* _upb_WireReader_SkipValue( |
|
|
|
UPB_INLINE const char* _upb_WireReader_SkipValue( |
|
|
@ -173,7 +143,8 @@ UPB_INLINE const char* _upb_WireReader_SkipValue( |
|
|
|
return ptr; |
|
|
|
return ptr; |
|
|
|
} |
|
|
|
} |
|
|
|
case kUpb_WireType_StartGroup: |
|
|
|
case kUpb_WireType_StartGroup: |
|
|
|
return _upb_WireReader_SkipGroup(ptr, tag, depth_limit, stream); |
|
|
|
return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, depth_limit, |
|
|
|
|
|
|
|
stream); |
|
|
|
case kUpb_WireType_EndGroup: |
|
|
|
case kUpb_WireType_EndGroup: |
|
|
|
return NULL; // Should be handled before now.
|
|
|
|
return NULL; // Should be handled before now.
|
|
|
|
default: |
|
|
|
default: |
|
|
|