blob: 0414432a9512aa5adef08ec5414a04d1ec88c916 [file] [log] [blame]
Adam Cozzette501ecec2023-09-26 14:36:20 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
Adam Cozzette501ecec2023-09-26 14:36:20 -07003//
Protobuf Team Bot0fab7732023-11-20 13:38:15 -08004// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
Adam Cozzette501ecec2023-09-26 14:36:20 -07007
Eric Salo07fba1d2023-09-29 14:50:56 -07008#ifndef UPB_MESSAGE_INTERNAL_ARRAY_H_
9#define UPB_MESSAGE_INTERNAL_ARRAY_H_
Adam Cozzette501ecec2023-09-26 14:36:20 -070010
Eric Salofacf9592024-01-09 12:58:32 -080011#include <stdint.h>
Adam Cozzette501ecec2023-09-26 14:36:20 -070012#include <string.h>
13
Eric Salo7e1fd682023-12-27 18:43:45 -080014#include "upb/mem/arena.h"
Adam Cozzette501ecec2023-09-26 14:36:20 -070015
16// Must be last.
17#include "upb/port/def.inc"
18
Eric Salo8324c902023-11-17 17:15:35 -080019#define _UPB_ARRAY_MASK_IMM 0x4 // Frozen/immutable bit.
20#define _UPB_ARRAY_MASK_LG2 0x3 // Encoded elem size.
21#define _UPB_ARRAY_MASK_ALL (_UPB_ARRAY_MASK_IMM | _UPB_ARRAY_MASK_LG2)
22
Adam Cozzette501ecec2023-09-26 14:36:20 -070023#ifdef __cplusplus
24extern "C" {
25#endif
26
Eric Salo73037582024-01-29 12:10:27 -080027// LINT.IfChange(upb_Array)
28
Adam Cozzette501ecec2023-09-26 14:36:20 -070029// Our internal representation for repeated fields.
30struct upb_Array {
Eric Salo8324c902023-11-17 17:15:35 -080031 // This is a tagged pointer. Bits #0 and #1 encode the elem size as follows:
32 // 0 maps to elem size 1
33 // 1 maps to elem size 4
34 // 2 maps to elem size 8
35 // 3 maps to elem size 16
36 //
Eric Salo7b6a8452024-01-26 13:10:15 -080037 // Bit #2 contains the frozen/immutable flag.
Eric Salofacf9592024-01-09 12:58:32 -080038 uintptr_t UPB_ONLYBITS(data);
Eric Salo8324c902023-11-17 17:15:35 -080039
Eric Saloa4a98bd2023-12-18 16:01:38 -080040 size_t UPB_ONLYBITS(size); // The number of elements in the array.
Eric Salo3ce2c572023-11-27 10:45:25 -080041 size_t UPB_PRIVATE(capacity); // Allocated storage. Measured in elements.
Adam Cozzette501ecec2023-09-26 14:36:20 -070042};
Adam Cozzette501ecec2023-09-26 14:36:20 -070043
Eric Salo7b6a8452024-01-26 13:10:15 -080044UPB_INLINE void UPB_PRIVATE(_upb_Array_ShallowFreeze)(struct upb_Array* arr) {
45 arr->UPB_ONLYBITS(data) |= _UPB_ARRAY_MASK_IMM;
46}
47
Eric Salob0d3a782024-02-08 13:37:50 -080048UPB_API_INLINE bool upb_Array_IsFrozen(const struct upb_Array* arr) {
Eric Salo7b6a8452024-01-26 13:10:15 -080049 return (arr->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_IMM) != 0;
50}
51
Eric Salo7e1fd682023-12-27 18:43:45 -080052UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array,
Eric Salo3ce2c572023-11-27 10:45:25 -080053 void* data, size_t lg2) {
Eric Salo8324c902023-11-17 17:15:35 -080054 UPB_ASSERT(lg2 != 1);
55 UPB_ASSERT(lg2 <= 4);
56 const size_t bits = lg2 - (lg2 != 0);
Eric Salofacf9592024-01-09 12:58:32 -080057 array->UPB_ONLYBITS(data) = (uintptr_t)data | bits;
Eric Salo8324c902023-11-17 17:15:35 -080058}
59
Eric Salo7e1fd682023-12-27 18:43:45 -080060UPB_INLINE size_t
61UPB_PRIVATE(_upb_Array_ElemSizeLg2)(const struct upb_Array* array) {
Eric Salofacf9592024-01-09 12:58:32 -080062 const size_t bits = array->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_LG2;
Eric Salo8324c902023-11-17 17:15:35 -080063 const size_t lg2 = bits + (bits != 0);
64 return lg2;
Adam Cozzette501ecec2023-09-26 14:36:20 -070065}
66
Eric Salob0d3a782024-02-08 13:37:50 -080067UPB_API_INLINE const void* upb_Array_DataPtr(const struct upb_Array* array) {
Eric Salo3ce2c572023-11-27 10:45:25 -080068 UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); // Check assertions.
Eric Salofacf9592024-01-09 12:58:32 -080069 return (void*)(array->UPB_ONLYBITS(data) & ~(uintptr_t)_UPB_ARRAY_MASK_ALL);
Adam Cozzette501ecec2023-09-26 14:36:20 -070070}
71
Eric Salob0d3a782024-02-08 13:37:50 -080072UPB_API_INLINE void* upb_Array_MutableDataPtr(struct upb_Array* array) {
73 return (void*)upb_Array_DataPtr(array);
Adam Cozzette501ecec2023-09-26 14:36:20 -070074}
75
Eric Salo7e1fd682023-12-27 18:43:45 -080076UPB_INLINE struct upb_Array* UPB_PRIVATE(_upb_Array_New)(upb_Arena* arena,
77 size_t init_capacity,
78 int elem_size_lg2) {
Eric Salo8324c902023-11-17 17:15:35 -080079 UPB_ASSERT(elem_size_lg2 != 1);
Adam Cozzette501ecec2023-09-26 14:36:20 -070080 UPB_ASSERT(elem_size_lg2 <= 4);
Eric Salo7e1fd682023-12-27 18:43:45 -080081 const size_t array_size =
82 UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN);
Eric Salo3ce2c572023-11-27 10:45:25 -080083 const size_t bytes = array_size + (init_capacity << elem_size_lg2);
Eric Salo7e1fd682023-12-27 18:43:45 -080084 struct upb_Array* array = (struct upb_Array*)upb_Arena_Malloc(arena, bytes);
Eric Salo3ce2c572023-11-27 10:45:25 -080085 if (!array) return NULL;
86 UPB_PRIVATE(_upb_Array_SetTaggedPtr)
87 (array, UPB_PTR_AT(array, array_size, void), elem_size_lg2);
Eric Saloa4a98bd2023-12-18 16:01:38 -080088 array->UPB_ONLYBITS(size) = 0;
Eric Salo3ce2c572023-11-27 10:45:25 -080089 array->UPB_PRIVATE(capacity) = init_capacity;
90 return array;
Adam Cozzette501ecec2023-09-26 14:36:20 -070091}
92
93// Resizes the capacity of the array to be at least min_size.
Eric Salo7e1fd682023-12-27 18:43:45 -080094bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size,
Eric Salo3ce2c572023-11-27 10:45:25 -080095 upb_Arena* arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -070096
Eric Salo7e1fd682023-12-27 18:43:45 -080097UPB_INLINE bool UPB_PRIVATE(_upb_Array_Reserve)(struct upb_Array* array,
98 size_t size, upb_Arena* arena) {
Eric Salob0d3a782024-02-08 13:37:50 -080099 UPB_ASSERT(!upb_Array_IsFrozen(array));
Eric Salo3ce2c572023-11-27 10:45:25 -0800100 if (array->UPB_PRIVATE(capacity) < size)
101 return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700102 return true;
103}
104
105// Resize without initializing new elements.
Eric Saloc7f44a02024-01-11 12:48:38 -0800106UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
107 struct upb_Array* array, size_t size, upb_Arena* arena) {
Eric Salob0d3a782024-02-08 13:37:50 -0800108 UPB_ASSERT(!upb_Array_IsFrozen(array));
Eric Saloa4a98bd2023-12-18 16:01:38 -0800109 UPB_ASSERT(size <= array->UPB_ONLYBITS(size) ||
110 arena); // Allow NULL arena when shrinking.
Eric Salo3ce2c572023-11-27 10:45:25 -0800111 if (!UPB_PRIVATE(_upb_Array_Reserve)(array, size, arena)) return false;
Eric Saloa4a98bd2023-12-18 16:01:38 -0800112 array->UPB_ONLYBITS(size) = size;
Adam Cozzette501ecec2023-09-26 14:36:20 -0700113 return true;
114}
115
116// This function is intended for situations where elem_size is compile-time
117// constant or a known expression of the form (1 << lg2), so that the expression
118// i*elem_size does not result in an actual multiplication.
Eric Salo7e1fd682023-12-27 18:43:45 -0800119UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i,
Eric Salo3ce2c572023-11-27 10:45:25 -0800120 const void* data,
121 size_t elem_size) {
Eric Salob0d3a782024-02-08 13:37:50 -0800122 UPB_ASSERT(!upb_Array_IsFrozen(array));
Eric Saloa4a98bd2023-12-18 16:01:38 -0800123 UPB_ASSERT(i < array->UPB_ONLYBITS(size));
Eric Salo3ce2c572023-11-27 10:45:25 -0800124 UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array));
Eric Salob0d3a782024-02-08 13:37:50 -0800125 char* arr_data = (char*)upb_Array_MutableDataPtr(array);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700126 memcpy(arr_data + (i * elem_size), data, elem_size);
127}
128
Eric Salob0d3a782024-02-08 13:37:50 -0800129UPB_API_INLINE size_t upb_Array_Size(const struct upb_Array* arr) {
Eric Saloc7f44a02024-01-11 12:48:38 -0800130 return arr->UPB_ONLYBITS(size);
131}
132
Eric Salo73037582024-01-29 12:10:27 -0800133// LINT.ThenChange(GoogleInternalName0)
Protobuf Team Bot2ff245e2023-12-01 11:06:30 -0800134
Adam Cozzette501ecec2023-09-26 14:36:20 -0700135#ifdef __cplusplus
136} /* extern "C" */
137#endif
138
Eric Salo8324c902023-11-17 17:15:35 -0800139#undef _UPB_ARRAY_MASK_IMM
140#undef _UPB_ARRAY_MASK_LG2
141#undef _UPB_ARRAY_MASK_ALL
142
Adam Cozzette501ecec2023-09-26 14:36:20 -0700143#include "upb/port/undef.inc"
144
Eric Salo07fba1d2023-09-29 14:50:56 -0700145#endif /* UPB_MESSAGE_INTERNAL_ARRAY_H_ */