// 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 GOOGLE_UPB_UPB_WIRE_INTERNAL_BACK_ALLOC_H__ #define GOOGLE_UPB_UPB_WIRE_INTERNAL_BACK_ALLOC_H__ #include #include "upb/mem/arena.h" #include "upb/mem/internal/arena.h" // Must be last. #include "upb/port/def.inc" #ifdef __cplusplus extern "C" { #endif // Allocates memory from the back of the arena. typedef struct { upb_Arena* arena; char *buf, *limit; bool standalone; } upb_BackAlloc; // Needed because C doesn't allow NULL - NULL. extern char upb_BackAlloc_sentinel; char* upb_BackAlloc_Grow(upb_BackAlloc* a, char* ptr, size_t need); UPB_INLINE char* upb_BackAlloc_Init(upb_BackAlloc* a, upb_Arena* arena) { a->arena = arena; // This could eagerly steal whatever's in the arena, since stealing with a // minimum of 0 can't fail. a->buf = &upb_BackAlloc_sentinel; a->limit = &upb_BackAlloc_sentinel; a->standalone = false; return a->limit; } UPB_INLINE void upb_BackAlloc_Abort(upb_BackAlloc* a) { if (a->standalone) { UPB_PRIVATE(_upb_Arena_FreeBlock)(a->arena, a->buf); } else if (a->limit != a->buf) { UPB_PRIVATE(_upb_Arena_UseBlock)(a->arena, a->buf, a->limit - a->buf); } } UPB_INLINE size_t upb_BackAlloc_Finish(upb_BackAlloc* a, const char* ptr) { if (a->standalone) { UPB_PRIVATE(_upb_Arena_AddBlock)(a->arena, a->buf); } if (ptr != a->buf) { UPB_PRIVATE(_upb_Arena_UseBlock)(a->arena, a->buf, ptr - a->buf); } return a->limit - ptr; } UPB_FORCEINLINE bool upb_BackAlloc_HasBytes(const upb_BackAlloc* a, const char* ptr, size_t need) { size_t have = ptr - a->buf; return have >= need; } UPB_FORCEINLINE char* upb_BackAlloc_Reserve(upb_BackAlloc* a, char* ptr, size_t need) { return upb_BackAlloc_HasBytes(a, ptr, need) ? ptr - need : upb_BackAlloc_Grow(a, ptr, need); } UPB_INLINE size_t upb_BackAlloc_Size(const upb_BackAlloc* a, const char* ptr) { return a->limit - ptr; } #ifdef __cplusplus } /* extern "C" */ #endif #include "upb/port/undef.inc" #endif // GOOGLE_UPB_UPB_WIRE_INTERNAL_BACK_ALLOC_H__