• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  All rights reserved.
3 //
4 // 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
7 
8 #include "upb/mini_table/extension_registry.h"
9 
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <string.h>
13 
14 #include "upb/hash/str_table.h"
15 #include "upb/mem/arena.h"
16 #include "upb/mini_table/extension.h"
17 #include "upb/mini_table/message.h"
18 
19 // Must be last.
20 #include "upb/port/def.inc"
21 
22 #define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
23 
24 struct upb_ExtensionRegistry {
25   upb_Arena* arena;
26   upb_strtable exts;  // Key is upb_MiniTable* concatenated with fieldnum.
27 };
28 
extreg_key(char * buf,const upb_MiniTable * l,uint32_t fieldnum)29 static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
30   memcpy(buf, &l, sizeof(l));
31   memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
32 }
33 
upb_ExtensionRegistry_New(upb_Arena * arena)34 upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
35   upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
36   if (!r) return NULL;
37   r->arena = arena;
38   if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
39   return r;
40 }
41 
upb_ExtensionRegistry_Add(upb_ExtensionRegistry * r,const upb_MiniTableExtension * e)42 UPB_API bool upb_ExtensionRegistry_Add(upb_ExtensionRegistry* r,
43                                        const upb_MiniTableExtension* e) {
44   char buf[EXTREG_KEY_SIZE];
45   extreg_key(buf, e->UPB_PRIVATE(extendee), upb_MiniTableExtension_Number(e));
46   if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, NULL)) return false;
47   return upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
48                              upb_value_constptr(e), r->arena);
49 }
50 
upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry * r,const upb_MiniTableExtension ** e,size_t count)51 bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r,
52                                     const upb_MiniTableExtension** e,
53                                     size_t count) {
54   const upb_MiniTableExtension** start = e;
55   const upb_MiniTableExtension** end = UPB_PTRADD(e, count);
56   for (; e < end; e++) {
57     if (!upb_ExtensionRegistry_Add(r, *e)) goto failure;
58   }
59   return true;
60 
61 failure:
62   // Back out the entries previously added.
63   for (end = e, e = start; e < end; e++) {
64     const upb_MiniTableExtension* ext = *e;
65     char buf[EXTREG_KEY_SIZE];
66     extreg_key(buf, ext->UPB_PRIVATE(extendee),
67                upb_MiniTableExtension_Number(ext));
68     upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
69   }
70   return false;
71 }
72 
73 #ifdef UPB_LINKARR_DECLARE
74 
75 UPB_LINKARR_DECLARE(upb_AllExts, upb_MiniTableExtension);
76 
upb_ExtensionRegistry_AddAllLinkedExtensions(upb_ExtensionRegistry * r)77 bool upb_ExtensionRegistry_AddAllLinkedExtensions(upb_ExtensionRegistry* r) {
78   const upb_MiniTableExtension* start = UPB_LINKARR_START(upb_AllExts);
79   const upb_MiniTableExtension* stop = UPB_LINKARR_STOP(upb_AllExts);
80   for (const upb_MiniTableExtension* p = start; p < stop; p++) {
81     // Windows can introduce zero padding, so we have to skip zeroes.
82     if (upb_MiniTableExtension_Number(p) != 0) {
83       if (!upb_ExtensionRegistry_Add(r, p)) return false;
84     }
85   }
86   return true;
87 }
88 
89 #endif  // UPB_LINKARR_DECLARE
90 
upb_ExtensionRegistry_Lookup(const upb_ExtensionRegistry * r,const upb_MiniTable * t,uint32_t num)91 const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup(
92     const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num) {
93   char buf[EXTREG_KEY_SIZE];
94   upb_value v;
95   extreg_key(buf, t, num);
96   if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
97     return upb_value_getconstptr(v);
98   } else {
99     return NULL;
100   }
101 }
102