• 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_output_stream.h"
9 
10 // Must be last.
11 #include "upb/port/def.inc"
12 
13 typedef struct {
14   upb_ZeroCopyOutputStream base;
15 
16   char* data;
17   size_t size;
18   size_t limit;
19   size_t position;
20   size_t last_returned_size;
21 } upb_ChunkedOutputStream;
22 
upb_ChunkedOutputStream_Next(upb_ZeroCopyOutputStream * z,size_t * count,upb_Status * status)23 static void* upb_ChunkedOutputStream_Next(upb_ZeroCopyOutputStream* z,
24                                           size_t* count, upb_Status* status) {
25   upb_ChunkedOutputStream* c = (upb_ChunkedOutputStream*)z;
26   UPB_ASSERT(c->position <= c->size);
27 
28   char* out = c->data + c->position;
29 
30   const size_t chunk = UPB_MIN(c->limit, c->size - c->position);
31   c->position += chunk;
32   c->last_returned_size = chunk;
33   *count = chunk;
34 
35   return chunk ? out : NULL;
36 }
37 
upb_ChunkedOutputStream_BackUp(upb_ZeroCopyOutputStream * z,size_t count)38 static void upb_ChunkedOutputStream_BackUp(upb_ZeroCopyOutputStream* z,
39                                            size_t count) {
40   upb_ChunkedOutputStream* c = (upb_ChunkedOutputStream*)z;
41 
42   UPB_ASSERT(c->last_returned_size >= count);
43   c->position -= count;
44   c->last_returned_size -= count;
45 }
46 
upb_ChunkedOutputStream_ByteCount(const upb_ZeroCopyOutputStream * z)47 static size_t upb_ChunkedOutputStream_ByteCount(
48     const upb_ZeroCopyOutputStream* z) {
49   const upb_ChunkedOutputStream* c = (const upb_ChunkedOutputStream*)z;
50 
51   return c->position;
52 }
53 
54 static const _upb_ZeroCopyOutputStream_VTable upb_ChunkedOutputStream_vtable = {
55     upb_ChunkedOutputStream_Next,
56     upb_ChunkedOutputStream_BackUp,
57     upb_ChunkedOutputStream_ByteCount,
58 };
59 
upb_ChunkedOutputStream_New(void * data,size_t size,size_t limit,upb_Arena * arena)60 upb_ZeroCopyOutputStream* upb_ChunkedOutputStream_New(void* data, size_t size,
61                                                       size_t limit,
62                                                       upb_Arena* arena) {
63   upb_ChunkedOutputStream* c = upb_Arena_Malloc(arena, sizeof(*c));
64   if (!c || !limit) return NULL;
65 
66   c->base.vtable = &upb_ChunkedOutputStream_vtable;
67   c->data = data;
68   c->size = size;
69   c->limit = limit;
70   c->position = 0;
71   c->last_returned_size = 0;
72 
73   return (upb_ZeroCopyOutputStream*)c;
74 }
75