Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:25:25

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2023 Google LLC.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 #ifndef UPB_WIRE_READER_H_
0009 #define UPB_WIRE_READER_H_
0010 
0011 #include "upb/base/internal/endian.h"
0012 #include "upb/wire/eps_copy_input_stream.h"
0013 #include "upb/wire/internal/reader.h"
0014 #include "upb/wire/types.h"  // IWYU pragma: export
0015 
0016 // Must be last.
0017 #include "upb/port/def.inc"
0018 
0019 // The upb_WireReader interface is suitable for general-purpose parsing of
0020 // protobuf binary wire format. It is designed to be used along with
0021 // upb_EpsCopyInputStream for buffering, and all parsing routines in this file
0022 // assume that at least kUpb_EpsCopyInputStream_SlopBytes worth of data is
0023 // available to read without any bounds checks.
0024 
0025 #ifdef __cplusplus
0026 extern "C" {
0027 #endif
0028 
0029 // Parses a tag into `tag`, and returns a pointer past the end of the tag, or
0030 // NULL if there was an error in the tag data.
0031 //
0032 // REQUIRES: there must be at least 10 bytes of data available at `ptr`.
0033 // Bounds checks must be performed before calling this function, preferably
0034 // by calling upb_EpsCopyInputStream_IsDone().
0035 UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr,
0036                                                    uint32_t* tag) {
0037   uint64_t val;
0038   ptr = UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, &val, 5, UINT32_MAX);
0039   if (!ptr) return NULL;
0040   *tag = val;
0041   return ptr;
0042 }
0043 
0044 // Given a tag, returns the field number.
0045 UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag);
0046 
0047 // Given a tag, returns the wire type.
0048 UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag);
0049 
0050 UPB_INLINE const char* upb_WireReader_ReadVarint(const char* ptr,
0051                                                  uint64_t* val) {
0052   return UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, val, 10, UINT64_MAX);
0053 }
0054 
0055 // Skips data for a varint, returning a pointer past the end of the varint, or
0056 // NULL if there was an error in the varint data.
0057 //
0058 // REQUIRES: there must be at least 10 bytes of data available at `ptr`.
0059 // Bounds checks must be performed before calling this function, preferably
0060 // by calling upb_EpsCopyInputStream_IsDone().
0061 UPB_INLINE const char* upb_WireReader_SkipVarint(const char* ptr) {
0062   uint64_t val;
0063   return upb_WireReader_ReadVarint(ptr, &val);
0064 }
0065 
0066 // Reads a varint indicating the size of a delimited field into `size`, or
0067 // NULL if there was an error in the varint data.
0068 //
0069 // REQUIRES: there must be at least 10 bytes of data available at `ptr`.
0070 // Bounds checks must be performed before calling this function, preferably
0071 // by calling upb_EpsCopyInputStream_IsDone().
0072 UPB_INLINE const char* upb_WireReader_ReadSize(const char* ptr, int* size) {
0073   uint64_t size64;
0074   ptr = upb_WireReader_ReadVarint(ptr, &size64);
0075   if (!ptr || size64 >= INT32_MAX) return NULL;
0076   *size = size64;
0077   return ptr;
0078 }
0079 
0080 // Reads a fixed32 field, performing byte swapping if necessary.
0081 //
0082 // REQUIRES: there must be at least 4 bytes of data available at `ptr`.
0083 // Bounds checks must be performed before calling this function, preferably
0084 // by calling upb_EpsCopyInputStream_IsDone().
0085 UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) {
0086   uint32_t uval;
0087   memcpy(&uval, ptr, 4);
0088   uval = upb_BigEndian32(uval);
0089   memcpy(val, &uval, 4);
0090   return ptr + 4;
0091 }
0092 
0093 // Reads a fixed64 field, performing byte swapping if necessary.
0094 //
0095 // REQUIRES: there must be at least 4 bytes of data available at `ptr`.
0096 // Bounds checks must be performed before calling this function, preferably
0097 // by calling upb_EpsCopyInputStream_IsDone().
0098 UPB_INLINE const char* upb_WireReader_ReadFixed64(const char* ptr, void* val) {
0099   uint64_t uval;
0100   memcpy(&uval, ptr, 8);
0101   uval = upb_BigEndian64(uval);
0102   memcpy(val, &uval, 8);
0103   return ptr + 8;
0104 }
0105 
0106 const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)(
0107     const char* ptr, uint32_t tag, int depth_limit,
0108     upb_EpsCopyInputStream* stream);
0109 
0110 // Skips data for a group, returning a pointer past the end of the group, or
0111 // NULL if there was an error parsing the group.  The `tag` argument should be
0112 // the start group tag that begins the group.  The `depth_limit` argument
0113 // indicates how many levels of recursion the group is allowed to have before
0114 // reporting a parse error (this limit exists to protect against stack
0115 // overflow).
0116 //
0117 // TODO: evaluate how the depth_limit should be specified. Do users need
0118 // control over this?
0119 UPB_INLINE const char* upb_WireReader_SkipGroup(
0120     const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) {
0121   return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, 100, stream);
0122 }
0123 
0124 UPB_INLINE const char* _upb_WireReader_SkipValue(
0125     const char* ptr, uint32_t tag, int depth_limit,
0126     upb_EpsCopyInputStream* stream) {
0127   switch (upb_WireReader_GetWireType(tag)) {
0128     case kUpb_WireType_Varint:
0129       return upb_WireReader_SkipVarint(ptr);
0130     case kUpb_WireType_32Bit:
0131       return ptr + 4;
0132     case kUpb_WireType_64Bit:
0133       return ptr + 8;
0134     case kUpb_WireType_Delimited: {
0135       int size;
0136       ptr = upb_WireReader_ReadSize(ptr, &size);
0137       if (!ptr) return NULL;
0138       ptr += size;
0139       return ptr;
0140     }
0141     case kUpb_WireType_StartGroup:
0142       return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, depth_limit,
0143                                                     stream);
0144     case kUpb_WireType_EndGroup:
0145       return NULL;  // Should be handled before now.
0146     default:
0147       return NULL;  // Unknown wire type.
0148   }
0149 }
0150 
0151 // Skips data for a wire value of any type, returning a pointer past the end of
0152 // the data, or NULL if there was an error parsing the group. The `tag` argument
0153 // should be the tag that was just parsed. The `depth_limit` argument indicates
0154 // how many levels of recursion a group is allowed to have before reporting a
0155 // parse error (this limit exists to protect against stack overflow).
0156 //
0157 // REQUIRES: there must be at least 10 bytes of data available at `ptr`.
0158 // Bounds checks must be performed before calling this function, preferably
0159 // by calling upb_EpsCopyInputStream_IsDone().
0160 //
0161 // TODO: evaluate how the depth_limit should be specified. Do users need
0162 // control over this?
0163 UPB_INLINE const char* upb_WireReader_SkipValue(
0164     const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) {
0165   return _upb_WireReader_SkipValue(ptr, tag, 100, stream);
0166 }
0167 
0168 #ifdef __cplusplus
0169 } /* extern "C" */
0170 #endif
0171 
0172 #include "upb/port/undef.inc"
0173 
0174 #endif  // UPB_WIRE_READER_H_