Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-28 09:30:13

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