| // Protocol Buffers - Google's data interchange format |
| // Copyright 2023 Google LLC. All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file or at |
| // https://developers.google.com/open-source/licenses/bsd |
| |
| #ifndef UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ |
| #define UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include "upb/base/error_handler.h" |
| #include "upb/base/string_view.h" |
| #include "upb/wire/internal/eps_copy_input_stream.h" |
| |
| // Must be last. |
| #include "upb/port/def.inc" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| typedef struct upb_EpsCopyCapture upb_EpsCopyCapture; |
| typedef struct upb_EpsCopyInputStream upb_EpsCopyInputStream; |
| |
| // Initializes a upb_EpsCopyInputStream using the contents of the buffer |
| // [*ptr, size]. Updates `*ptr` as necessary to guarantee that at least |
| // kUpb_EpsCopyInputStream_SlopBytes are available to read. |
| UPB_INLINE void upb_EpsCopyInputStream_Init(upb_EpsCopyInputStream* e, |
| const char** ptr, size_t size); |
| |
| // Like the previous function, but registers an error handler that will be |
| // called for any errors encountered. |
| UPB_INLINE void upb_EpsCopyInputStream_InitWithErrorHandler( |
| upb_EpsCopyInputStream* e, const char** ptr, size_t size, |
| upb_ErrorHandler* err); |
| |
| // Returns true if the stream has an error handler. |
| // |
| // This function is marked const, which indicates to the compiler that the |
| // return value is solely a function of the pointer value. This is not |
| // entirely true if the stream is reinitialized with |
| // upb_EpsCopyInputStream_Init*(), so users must not call this function in |
| // any context where the stream may be reinitialized between calls to this |
| // function, and the presence of an error handler changes when reinitialized. |
| UPB_ATTR_CONST |
| UPB_INLINE bool upb_EpsCopyInputStream_HasErrorHandler( |
| const upb_EpsCopyInputStream* e); |
| |
| // Returns true if the stream is in the error state. A stream enters the error |
| // state when the user reads past a limit (caught in IsDone()) or the |
| // ZeroCopyInputStream returns an error. |
| UPB_INLINE bool upb_EpsCopyInputStream_IsError(upb_EpsCopyInputStream* e); |
| |
| // Returns true if the stream has hit a limit, either the current delimited |
| // limit or the overall end-of-stream. As a side effect, this function may flip |
| // the pointer to a new buffer if there are less than |
| // kUpb_EpsCopyInputStream_SlopBytes of data to be read in the current buffer. |
| // |
| // Postcondition: if the function returns false, there are at least |
| // kUpb_EpsCopyInputStream_SlopBytes of data available to read at *ptr. |
| // |
| // If this returns true, the user must call upb_EpsCopyInputStream_IsError() |
| // to distinguish between EOF and error. |
| UPB_INLINE bool upb_EpsCopyInputStream_IsDone(upb_EpsCopyInputStream* e, |
| const char** ptr); |
| |
| // Returns true if the given delimited field size is valid (it does not extend |
| // beyond any previously-pushed limits). `ptr` should point to the beginning |
| // of the field data, after the delimited size. |
| // |
| // Note that this does *not* guarantee that all of the data for this field is in |
| // the current buffer. |
| UPB_INLINE bool upb_EpsCopyInputStream_CheckSize( |
| const upb_EpsCopyInputStream* e, const char* ptr, int size); |
| |
| // Marks the start of a capture operation. The capture operation will be |
| // finalized by a call to upb_EpsCopyCapture_End(). The captured string will |
| // be returned in sv, and will point to the original input buffer if possible. |
| UPB_INLINE void upb_EpsCopyCapture_Start(upb_EpsCopyCapture* c, |
| upb_EpsCopyInputStream* e, |
| const char* ptr); |
| |
| // Ends a capture operation and returns the captured string. Returns false if |
| // the capture operation was invalid (the parsing pointer extends beyond the |
| // end of the stream). |
| UPB_INLINE bool upb_EpsCopyCapture_End(upb_EpsCopyCapture* c, |
| upb_EpsCopyInputStream* e, |
| const char* ptr, upb_StringView* sv); |
| |
| // Reads a string from the stream and advances the pointer accordingly. The |
| // returned string view will always alias the input buffer. |
| // |
| // Returns NULL if size extends beyond the end of the current input buffer. |
| // Currently, we only support a single input buffer, so this function will only |
| // fail if `size` overflows the end of the stream. |
| // |
| // If/when we support multiple input buffers, there may be cases where this |
| // function returns failure, even if the requested region is valid, because the |
| // requested region spans multiple buffers. In this case, the caller must |
| // attempt to read the string using other string reading functions before |
| // signaling an error. |
| UPB_INLINE const char* upb_EpsCopyInputStream_ReadStringAlwaysAlias( |
| upb_EpsCopyInputStream* e, const char* ptr, size_t size, |
| upb_StringView* sv); |
| |
| // Reads a string from the stream and advances the pointer accordingly. The |
| // returned string view is ephemeral, only valid until the next call to |
| // upb_EpsCopyInputStream. It may point to the patch buffer. |
| // |
| // Returns NULL if size extends beyond the end of the current buffer (which may |
| // be the patch buffer). |
| // |
| // IMPORTANT NOTE: If `size` extends beyond the end of the stream, the returned |
| // data may contain garbage bytes from the patch buffer. For efficiency, this |
| // function does not check that `size` is within the current limit or even the |
| // end of the stream. |
| // |
| // The bytes are guaranteed to be safe to read ephemerally, but they may contain |
| // garbage data that does not correspond to anything in the input. This error |
| // will be detected later, when calling upb_EpsCopyInputStream_IsDone() (because |
| // we will not end at the proper limit), but it may result in nonsense bytes |
| // ending up in the output. |
| UPB_INLINE const char* upb_EpsCopyInputStream_ReadStringEphemeral( |
| upb_EpsCopyInputStream* e, const char* ptr, size_t size, |
| upb_StringView* sv); |
| |
| // Pushes a limit onto the stack of limits for the current stream. The limit |
| // will extend for `size` bytes beyond the position in `ptr`. Future calls to |
| // upb_EpsCopyInputStream_IsDone() will return `true` when the stream position |
| // reaches this limit. |
| // |
| // Returns a delta that the caller must store and supply to PopLimit() below. |
| // |
| // A return value of <0 indicates that `size` is too large, and exceeds a |
| // previous limit. If this occurs, the stream is in an error state and must no |
| // longer be used. |
| UPB_INLINE ptrdiff_t upb_EpsCopyInputStream_PushLimit(upb_EpsCopyInputStream* e, |
| const char* ptr, |
| size_t size); |
| |
| // Pops the last limit that was pushed on this stream. This may only be called |
| // once IsDone() returns true. The user must pass the delta that was returned |
| // from PushLimit(). |
| UPB_INLINE void upb_EpsCopyInputStream_PopLimit(upb_EpsCopyInputStream* e, |
| const char* ptr, |
| ptrdiff_t saved_delta); |
| |
| // Tries to perform a fast-path handling of the given delimited message data. |
| // If the sub-message beginning at `*ptr` and extending for `len` is short and |
| // fits within this buffer, calls `func` with `ctx` as a parameter, where the |
| // pushing and popping of limits is handled automatically and with lower cost |
| // than the normal PushLimit()/PopLimit() sequence. |
| UPB_FORCEINLINE bool upb_EpsCopyInputStream_TryParseDelimitedFast( |
| upb_EpsCopyInputStream* e, const char** ptr, size_t size, |
| upb_EpsCopyInputStream_ParseDelimitedFunc* func, void* ctx); |
| |
| #ifdef __cplusplus |
| } /* extern "C" */ |
| #endif |
| |
| #ifdef __cplusplus |
| // Temporary overloads for functions whose signature has recently changed. |
| UPB_DEPRECATE_AND_INLINE() |
| UPB_INLINE void upb_EpsCopyInputStream_Init(upb_EpsCopyInputStream* e, |
| const char** ptr, size_t size, |
| bool enable_aliasing) { |
| upb_EpsCopyInputStream_Init(e, ptr, size); |
| } |
| #endif |
| |
| #include "upb/port/undef.inc" |
| |
| #endif // UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ |