blob: 29595e358262579466d7bc6d466f3740c73a5aa8 [file] [edit]
// 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_