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