• 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/io/chunked_input_stream.h"
9 
10 // Must be last.
11 #include "upb/port/def.inc"
12 
13 typedef struct {
14   upb_ZeroCopyInputStream base;
15 
16   const char* data;
17   size_t size;
18   size_t limit;
19   size_t position;
20   size_t last_returned_size;
21 } upb_ChunkedInputStream;
22 
upb_ChunkedInputStream_Next(upb_ZeroCopyInputStream * z,size_t * count,upb_Status * status)23 static const void* upb_ChunkedInputStream_Next(upb_ZeroCopyInputStream* z,
24                                                size_t* count,
25                                                upb_Status* status) {
26   upb_ChunkedInputStream* c = (upb_ChunkedInputStream*)z;
27   UPB_ASSERT(c->position <= c->size);
28 
29   const char* out = c->data + c->position;
30 
31   const size_t chunk = UPB_MIN(c->limit, c->size - c->position);
32   c->position += chunk;
33   c->last_returned_size = chunk;
34   *count = chunk;
35 
36   return chunk ? out : NULL;
37 }
38 
upb_ChunkedInputStream_BackUp(upb_ZeroCopyInputStream * z,size_t count)39 static void upb_ChunkedInputStream_BackUp(upb_ZeroCopyInputStream* z,
40                                           size_t count) {
41   upb_ChunkedInputStream* c = (upb_ChunkedInputStream*)z;
42 
43   UPB_ASSERT(c->last_returned_size >= count);
44   c->position -= count;
45   c->last_returned_size -= count;
46 }
47 
upb_ChunkedInputStream_Skip(upb_ZeroCopyInputStream * z,size_t count)48 static bool upb_ChunkedInputStream_Skip(upb_ZeroCopyInputStream* z,
49                                         size_t count) {
50   upb_ChunkedInputStream* c = (upb_ChunkedInputStream*)z;
51 
52   c->last_returned_size = 0;  // Don't let caller back up.
53   if (count > c->size - c->position) {
54     c->position = c->size;
55     return false;
56   }
57 
58   c->position += count;
59   return true;
60 }
61 
upb_ChunkedInputStream_ByteCount(const upb_ZeroCopyInputStream * z)62 static size_t upb_ChunkedInputStream_ByteCount(
63     const upb_ZeroCopyInputStream* z) {
64   const upb_ChunkedInputStream* c = (const upb_ChunkedInputStream*)z;
65 
66   return c->position;
67 }
68 
69 static const _upb_ZeroCopyInputStream_VTable upb_ChunkedInputStream_vtable = {
70     upb_ChunkedInputStream_Next,
71     upb_ChunkedInputStream_BackUp,
72     upb_ChunkedInputStream_Skip,
73     upb_ChunkedInputStream_ByteCount,
74 };
75 
upb_ChunkedInputStream_New(const void * data,size_t size,size_t limit,upb_Arena * arena)76 upb_ZeroCopyInputStream* upb_ChunkedInputStream_New(const void* data,
77                                                     size_t size, size_t limit,
78                                                     upb_Arena* arena) {
79   upb_ChunkedInputStream* c = upb_Arena_Malloc(arena, sizeof(*c));
80   if (!c || !limit) return NULL;
81 
82   c->base.vtable = &upb_ChunkedInputStream_vtable;
83   c->data = data;
84   c->size = size;
85   c->limit = limit;
86   c->position = 0;
87   c->last_returned_size = 0;
88 
89   return (upb_ZeroCopyInputStream*)c;
90 }
91