File indexing completed on 2026-08-11 09:41:46
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef UPB_WIRE_EPS_COPY_INPUT_STREAM_H_
0009 #define UPB_WIRE_EPS_COPY_INPUT_STREAM_H_
0010
0011 #include <stdint.h>
0012 #include <string.h>
0013
0014 #include "upb/mem/arena.h"
0015
0016
0017 #include "upb/port/def.inc"
0018
0019 #ifdef __cplusplus
0020 extern "C" {
0021 #endif
0022
0023
0024
0025
0026
0027
0028
0029 #define kUpb_EpsCopyInputStream_SlopBytes 16
0030
0031 typedef struct {
0032 const char* end;
0033 const char* limit_ptr;
0034 uintptr_t input_delta;
0035 const char* buffer_start;
0036 int limit;
0037 bool error;
0038 bool aliasing;
0039 char patch[kUpb_EpsCopyInputStream_SlopBytes * 2];
0040 } upb_EpsCopyInputStream;
0041
0042
0043
0044
0045 UPB_INLINE bool upb_EpsCopyInputStream_IsError(upb_EpsCopyInputStream* e) {
0046 return e->error;
0047 }
0048
0049 typedef const char* upb_EpsCopyInputStream_BufferFlipCallback(
0050 upb_EpsCopyInputStream* e, const char* old_end, const char* new_start);
0051
0052 typedef const char* upb_EpsCopyInputStream_IsDoneFallbackFunc(
0053 upb_EpsCopyInputStream* e, const char* ptr, int overrun);
0054
0055
0056
0057
0058 UPB_INLINE void upb_EpsCopyInputStream_Init(upb_EpsCopyInputStream* e,
0059 const char** ptr, size_t size,
0060 bool enable_aliasing) {
0061 e->buffer_start = *ptr;
0062 if (size <= kUpb_EpsCopyInputStream_SlopBytes) {
0063 memset(&e->patch, 0, 32);
0064 if (size) memcpy(&e->patch, *ptr, size);
0065 e->input_delta = (uintptr_t)*ptr - (uintptr_t)e->patch;
0066 *ptr = e->patch;
0067 e->end = *ptr + size;
0068 e->limit = 0;
0069 } else {
0070 e->end = *ptr + size - kUpb_EpsCopyInputStream_SlopBytes;
0071 e->limit = kUpb_EpsCopyInputStream_SlopBytes;
0072 e->input_delta = 0;
0073 }
0074 e->aliasing = enable_aliasing;
0075 e->limit_ptr = e->end;
0076 e->error = false;
0077 }
0078
0079 typedef enum {
0080
0081 kUpb_IsDoneStatus_Done,
0082
0083
0084 kUpb_IsDoneStatus_NotDone,
0085
0086
0087
0088 kUpb_IsDoneStatus_NeedFallback,
0089 } upb_IsDoneStatus;
0090
0091
0092
0093 UPB_INLINE upb_IsDoneStatus upb_EpsCopyInputStream_IsDoneStatus(
0094 upb_EpsCopyInputStream* e, const char* ptr, int* overrun) {
0095 *overrun = ptr - e->end;
0096 if (UPB_LIKELY(ptr < e->limit_ptr)) {
0097 return kUpb_IsDoneStatus_NotDone;
0098 } else if (UPB_LIKELY(*overrun == e->limit)) {
0099 return kUpb_IsDoneStatus_Done;
0100 } else {
0101 return kUpb_IsDoneStatus_NeedFallback;
0102 }
0103 }
0104
0105
0106
0107
0108
0109
0110
0111
0112 UPB_INLINE bool upb_EpsCopyInputStream_IsDoneWithCallback(
0113 upb_EpsCopyInputStream* e, const char** ptr,
0114 upb_EpsCopyInputStream_IsDoneFallbackFunc* func) {
0115 int overrun;
0116 switch (upb_EpsCopyInputStream_IsDoneStatus(e, *ptr, &overrun)) {
0117 case kUpb_IsDoneStatus_Done:
0118 return true;
0119 case kUpb_IsDoneStatus_NotDone:
0120 return false;
0121 case kUpb_IsDoneStatus_NeedFallback:
0122 *ptr = func(e, *ptr, overrun);
0123 return *ptr == NULL;
0124 }
0125 UPB_UNREACHABLE();
0126 }
0127
0128 const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback(
0129 upb_EpsCopyInputStream* e, const char* ptr, int overrun);
0130
0131
0132
0133
0134
0135
0136
0137 UPB_INLINE bool upb_EpsCopyInputStream_IsDone(upb_EpsCopyInputStream* e,
0138 const char** ptr) {
0139 return upb_EpsCopyInputStream_IsDoneWithCallback(
0140 e, ptr, _upb_EpsCopyInputStream_IsDoneFallbackNoCallback);
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 UPB_INLINE size_t upb_EpsCopyInputStream_BytesAvailable(
0152 upb_EpsCopyInputStream* e, const char* ptr) {
0153 return (e->end - ptr) + kUpb_EpsCopyInputStream_SlopBytes;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162 UPB_INLINE bool upb_EpsCopyInputStream_CheckSize(
0163 const upb_EpsCopyInputStream* e, const char* ptr, int size) {
0164 UPB_ASSERT(size >= 0);
0165 return size <= e->limit - (ptr - e->end);
0166 }
0167
0168 UPB_INLINE bool _upb_EpsCopyInputStream_CheckSizeAvailable(
0169 upb_EpsCopyInputStream* e, const char* ptr, int size, bool submessage) {
0170
0171
0172
0173
0174
0175 uintptr_t uptr = (uintptr_t)ptr;
0176 uintptr_t uend = (uintptr_t)e->limit_ptr;
0177 uintptr_t res = uptr + (size_t)size;
0178 if (!submessage) uend += kUpb_EpsCopyInputStream_SlopBytes;
0179
0180
0181 bool ret = res >= uptr && res <= uend;
0182 if (size < 0) UPB_ASSERT(!ret);
0183 return ret;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192 UPB_INLINE bool upb_EpsCopyInputStream_CheckDataSizeAvailable(
0193 upb_EpsCopyInputStream* e, const char* ptr, int size) {
0194 return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, false);
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 UPB_INLINE bool upb_EpsCopyInputStream_CheckSubMessageSizeAvailable(
0209 upb_EpsCopyInputStream* e, const char* ptr, int size) {
0210 return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, true);
0211 }
0212
0213
0214
0215 UPB_INLINE bool upb_EpsCopyInputStream_AliasingEnabled(
0216 upb_EpsCopyInputStream* e) {
0217 return e->aliasing;
0218 }
0219
0220
0221
0222
0223 UPB_INLINE bool upb_EpsCopyInputStream_AliasingAvailable(
0224 upb_EpsCopyInputStream* e, const char* ptr, size_t size) {
0225
0226
0227 return e->aliasing &&
0228 upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size);
0229 }
0230
0231
0232
0233
0234 UPB_INLINE const char* upb_EpsCopyInputStream_GetInputPtr(
0235 upb_EpsCopyInputStream* e, const char* ptr) {
0236
0237
0238
0239
0240 size_t position =
0241 (uintptr_t)ptr + e->input_delta - (uintptr_t)e->buffer_start;
0242 return e->buffer_start + position;
0243 }
0244
0245
0246
0247
0248
0249
0250
0251 UPB_INLINE const char* upb_EpsCopyInputStream_GetAliasedPtr(
0252 upb_EpsCopyInputStream* e, const char* ptr) {
0253 UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, ptr, 0));
0254 return upb_EpsCopyInputStream_GetInputPtr(e, ptr);
0255 }
0256
0257
0258
0259
0260
0261
0262
0263
0264 UPB_INLINE const char* upb_EpsCopyInputStream_ReadStringAliased(
0265 upb_EpsCopyInputStream* e, const char** ptr, size_t size) {
0266 UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size));
0267 const char* ret = *ptr + size;
0268 *ptr = upb_EpsCopyInputStream_GetAliasedPtr(e, *ptr);
0269 UPB_ASSUME(ret != NULL);
0270 return ret;
0271 }
0272
0273
0274
0275 UPB_INLINE const char* upb_EpsCopyInputStream_Skip(upb_EpsCopyInputStream* e,
0276 const char* ptr, int size) {
0277 if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL;
0278 return ptr + size;
0279 }
0280
0281
0282
0283 UPB_INLINE const char* upb_EpsCopyInputStream_Copy(upb_EpsCopyInputStream* e,
0284 const char* ptr, void* to,
0285 int size) {
0286 if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL;
0287 memcpy(to, ptr, size);
0288 return ptr + size;
0289 }
0290
0291
0292
0293
0294
0295
0296
0297
0298 UPB_INLINE const char* upb_EpsCopyInputStream_ReadString(
0299 upb_EpsCopyInputStream* e, const char** ptr, size_t size,
0300 upb_Arena* arena) {
0301 if (upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)) {
0302 return upb_EpsCopyInputStream_ReadStringAliased(e, ptr, size);
0303 } else {
0304
0305 if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, *ptr, size)) {
0306 return NULL;
0307 }
0308 UPB_ASSERT(arena);
0309 char* data = (char*)upb_Arena_Malloc(arena, size);
0310 if (!data) return NULL;
0311 const char* ret = upb_EpsCopyInputStream_Copy(e, *ptr, data, size);
0312 *ptr = data;
0313 return ret;
0314 }
0315 }
0316
0317 UPB_INLINE void _upb_EpsCopyInputStream_CheckLimit(upb_EpsCopyInputStream* e) {
0318 UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit));
0319 }
0320
0321
0322
0323
0324
0325
0326
0327 UPB_INLINE int upb_EpsCopyInputStream_PushLimit(upb_EpsCopyInputStream* e,
0328 const char* ptr, int size) {
0329 int limit = size + (int)(ptr - e->end);
0330 int delta = e->limit - limit;
0331 _upb_EpsCopyInputStream_CheckLimit(e);
0332 UPB_ASSERT(limit <= e->limit);
0333 e->limit = limit;
0334 e->limit_ptr = e->end + UPB_MIN(0, limit);
0335 _upb_EpsCopyInputStream_CheckLimit(e);
0336 return delta;
0337 }
0338
0339
0340
0341
0342 UPB_INLINE void upb_EpsCopyInputStream_PopLimit(upb_EpsCopyInputStream* e,
0343 const char* ptr,
0344 int saved_delta) {
0345 UPB_ASSERT(ptr - e->end == e->limit);
0346 _upb_EpsCopyInputStream_CheckLimit(e);
0347 e->limit += saved_delta;
0348 e->limit_ptr = e->end + UPB_MIN(0, e->limit);
0349 _upb_EpsCopyInputStream_CheckLimit(e);
0350 }
0351
0352 UPB_INLINE const char* _upb_EpsCopyInputStream_IsDoneFallbackInline(
0353 upb_EpsCopyInputStream* e, const char* ptr, int overrun,
0354 upb_EpsCopyInputStream_BufferFlipCallback* callback) {
0355 if (overrun < e->limit) {
0356
0357 UPB_ASSERT(overrun < kUpb_EpsCopyInputStream_SlopBytes);
0358 const char* old_end = ptr;
0359 const char* new_start = &e->patch[0] + overrun;
0360 memset(e->patch + kUpb_EpsCopyInputStream_SlopBytes, 0,
0361 kUpb_EpsCopyInputStream_SlopBytes);
0362 memcpy(e->patch, e->end, kUpb_EpsCopyInputStream_SlopBytes);
0363 ptr = new_start;
0364 e->end = &e->patch[kUpb_EpsCopyInputStream_SlopBytes];
0365 e->limit -= kUpb_EpsCopyInputStream_SlopBytes;
0366 e->limit_ptr = e->end + e->limit;
0367 UPB_ASSERT(ptr < e->limit_ptr);
0368 e->input_delta = (uintptr_t)old_end - (uintptr_t)new_start;
0369 return callback(e, old_end, new_start);
0370 } else {
0371 UPB_ASSERT(overrun > e->limit);
0372 e->error = true;
0373 return callback(e, NULL, NULL);
0374 }
0375 }
0376
0377 typedef const char* upb_EpsCopyInputStream_ParseDelimitedFunc(
0378 upb_EpsCopyInputStream* e, const char* ptr, void* ctx);
0379
0380
0381
0382
0383
0384
0385 UPB_FORCEINLINE bool upb_EpsCopyInputStream_TryParseDelimitedFast(
0386 upb_EpsCopyInputStream* e, const char** ptr, int len,
0387 upb_EpsCopyInputStream_ParseDelimitedFunc* func, void* ctx) {
0388 if (!upb_EpsCopyInputStream_CheckSubMessageSizeAvailable(e, *ptr, len)) {
0389 return false;
0390 }
0391
0392
0393
0394 const char* saved_limit_ptr = e->limit_ptr;
0395 int saved_limit = e->limit;
0396 e->limit_ptr = *ptr + len;
0397 e->limit = e->limit_ptr - e->end;
0398 UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit));
0399 *ptr = func(e, *ptr, ctx);
0400 e->limit_ptr = saved_limit_ptr;
0401 e->limit = saved_limit;
0402 UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit));
0403 return true;
0404 }
0405
0406 #ifdef __cplusplus
0407 }
0408 #endif
0409
0410 #include "upb/port/undef.inc"
0411
0412 #endif