Ruby  3.1.0dev(2021-09-10revisionb76ad15ed0da636161de0243c547ee1e6fc95681)
fbuffer.h
Go to the documentation of this file.
1 
2 #ifndef _FBUFFER_H_
3 #define _FBUFFER_H_
4 
5 #include "ruby.h"
6 
7 #ifndef RHASH_SIZE
8 #define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
9 #endif
10 
11 #ifndef RFLOAT_VALUE
12 #define RFLOAT_VALUE(val) (RFLOAT(val)->value)
13 #endif
14 
15 #ifndef RARRAY_LEN
16 #define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len
17 #endif
18 #ifndef RSTRING_PTR
19 #define RSTRING_PTR(string) RSTRING(string)->ptr
20 #endif
21 #ifndef RSTRING_LEN
22 #define RSTRING_LEN(string) RSTRING(string)->len
23 #endif
24 
25 #ifdef PRIsVALUE
26 # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
27 # define RB_OBJ_STRING(obj) (obj)
28 #else
29 # define PRIsVALUE "s"
30 # define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
31 # define RB_OBJ_STRING(obj) StringValueCStr(obj)
32 #endif
33 
34 #ifdef HAVE_RUBY_ENCODING_H
35 #include "ruby/encoding.h"
36 #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
37 #else
38 #define FORCE_UTF8(obj)
39 #endif
40 
41 /* We don't need to guard objects for rbx, so let's do nothing at all. */
42 #ifndef RB_GC_GUARD
43 #define RB_GC_GUARD(object)
44 #endif
45 
46 typedef struct FBufferStruct {
47  unsigned long initial_length;
48  char *ptr;
49  unsigned long len;
50  unsigned long capa;
51 } FBuffer;
52 
53 #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
54 
55 #define FBUFFER_PTR(fb) (fb->ptr)
56 #define FBUFFER_LEN(fb) (fb->len)
57 #define FBUFFER_CAPA(fb) (fb->capa)
58 #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
59 
60 static FBuffer *fbuffer_alloc(unsigned long initial_length);
61 static void fbuffer_free(FBuffer *fb);
62 static void fbuffer_clear(FBuffer *fb);
63 static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
64 #ifdef JSON_GENERATOR
65 static void fbuffer_append_long(FBuffer *fb, long number);
66 #endif
67 static void fbuffer_append_char(FBuffer *fb, char newchr);
68 #ifdef JSON_GENERATOR
69 static FBuffer *fbuffer_dup(FBuffer *fb);
70 static VALUE fbuffer_to_s(FBuffer *fb);
71 #endif
72 
73 static FBuffer *fbuffer_alloc(unsigned long initial_length)
74 {
75  FBuffer *fb;
76  if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
77  fb = ALLOC(FBuffer);
78  memset((void *) fb, 0, sizeof(FBuffer));
79  fb->initial_length = initial_length;
80  return fb;
81 }
82 
83 static void fbuffer_free(FBuffer *fb)
84 {
85  if (fb->ptr) ruby_xfree(fb->ptr);
86  ruby_xfree(fb);
87 }
88 
89 static void fbuffer_clear(FBuffer *fb)
90 {
91  fb->len = 0;
92 }
93 
94 static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
95 {
96  unsigned long required;
97 
98  if (!fb->ptr) {
99  fb->ptr = ALLOC_N(char, fb->initial_length);
100  fb->capa = fb->initial_length;
101  }
102 
103  for (required = fb->capa; requested > required - fb->len; required <<= 1);
104 
105  if (required > fb->capa) {
106  REALLOC_N(fb->ptr, char, required);
107  fb->capa = required;
108  }
109 }
110 
111 static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
112 {
113  if (len > 0) {
114  fbuffer_inc_capa(fb, len);
115  MEMCPY(fb->ptr + fb->len, newstr, char, len);
116  fb->len += len;
117  }
118 }
119 
120 #ifdef JSON_GENERATOR
121 static void fbuffer_append_str(FBuffer *fb, VALUE str)
122 {
123  const char *newstr = StringValuePtr(str);
124  unsigned long len = RSTRING_LEN(str);
125 
126  RB_GC_GUARD(str);
127 
128  fbuffer_append(fb, newstr, len);
129 }
130 #endif
131 
132 static void fbuffer_append_char(FBuffer *fb, char newchr)
133 {
134  fbuffer_inc_capa(fb, 1);
135  *(fb->ptr + fb->len) = newchr;
136  fb->len++;
137 }
138 
139 #ifdef JSON_GENERATOR
140 static void freverse(char *start, char *end)
141 {
142  char c;
143 
144  while (end > start) {
145  c = *end, *end-- = *start, *start++ = c;
146  }
147 }
148 
149 static long fltoa(long number, char *buf)
150 {
151  static char digits[] = "0123456789";
152  long sign = number;
153  char* tmp = buf;
154 
155  if (sign < 0) number = -number;
156  do *tmp++ = digits[number % 10]; while (number /= 10);
157  if (sign < 0) *tmp++ = '-';
158  freverse(buf, tmp - 1);
159  return tmp - buf;
160 }
161 
162 static void fbuffer_append_long(FBuffer *fb, long number)
163 {
164  char buf[20];
165  unsigned long len = fltoa(number, buf);
166  fbuffer_append(fb, buf, len);
167 }
168 
169 static FBuffer *fbuffer_dup(FBuffer *fb)
170 {
171  unsigned long len = fb->len;
172  FBuffer *result;
173 
174  result = fbuffer_alloc(len);
175  fbuffer_append(result, FBUFFER_PAIR(fb));
176  return result;
177 }
178 
179 static VALUE fbuffer_to_s(FBuffer *fb)
180 {
181  VALUE result = rb_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
182  fbuffer_free(fb);
183  FORCE_UTF8(result);
184  return result;
185 }
186 #endif
187 #endif
ruby_xfree
void ruby_xfree(void *x)
Deallocates a storage instance.
Definition: gc.c:11805
StringValuePtr
#define StringValuePtr(v)
Definition: rstring.h:51
ALLOC_N
#define ALLOC_N
Definition: memory.h:133
encoding.h
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: memory.h:129
FBufferStruct::capa
unsigned long capa
Definition: fbuffer.h:50
FBufferStruct::initial_length
unsigned long initial_length
Definition: fbuffer.h:47
RSTRING_LEN
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
REALLOC_N
#define REALLOC_N
Definition: memory.h:137
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
FBUFFER_INITIAL_LENGTH_DEFAULT
#define FBUFFER_INITIAL_LENGTH_DEFAULT
Definition: fbuffer.h:53
FBuffer
struct FBufferStruct FBuffer
len
uint8_t len
Definition: escape.c:17
ruby.h
FBufferStruct::len
unsigned long len
Definition: fbuffer.h:49
FBufferStruct::ptr
char * ptr
Definition: fbuffer.h:48
VALUE
unsigned long VALUE
Definition: value.h:38
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
FBufferStruct
Definition: fbuffer.h:46
FBUFFER_PTR
#define FBUFFER_PTR(fb)
Definition: fbuffer.h:55
FBUFFER_LEN
#define FBUFFER_LEN(fb)
Definition: fbuffer.h:56
FBUFFER_PAIR
#define FBUFFER_PAIR(fb)
Definition: fbuffer.h:58
FORCE_UTF8
#define FORCE_UTF8(obj)
Definition: fbuffer.h:36
ALLOC
#define ALLOC
Definition: memory.h:134
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: memory.h:91