Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
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
46typedef struct FBufferStruct {
47 unsigned long initial_length;
48 char *ptr;
49 unsigned long len;
50 unsigned long capa;
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
60static FBuffer *fbuffer_alloc(unsigned long initial_length);
61static void fbuffer_free(FBuffer *fb);
62static void fbuffer_clear(FBuffer *fb);
63static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
64#ifdef JSON_GENERATOR
65static void fbuffer_append_long(FBuffer *fb, long number);
66#endif
67static void fbuffer_append_char(FBuffer *fb, char newchr);
68#ifdef JSON_GENERATOR
69static FBuffer *fbuffer_dup(FBuffer *fb);
70static VALUE fbuffer_to_s(FBuffer *fb);
71#endif
72
73static 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
83static void fbuffer_free(FBuffer *fb)
84{
85 if (fb->ptr) ruby_xfree(fb->ptr);
86 ruby_xfree(fb);
87}
88
89static void fbuffer_clear(FBuffer *fb)
90{
91 fb->len = 0;
92}
93
94static 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
111static 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
121static void fbuffer_append_str(FBuffer *fb, VALUE str)
122{
123 const char *newstr = StringValuePtr(str);
124 unsigned long len = RSTRING_LEN(str);
125
127
128 fbuffer_append(fb, newstr, len);
129}
130#endif
131
132static 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
140static 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
149static 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
162static 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
169static 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
179static 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
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
#define FBUFFER_PAIR(fb)
Definition: fbuffer.h:58
struct FBufferStruct FBuffer
#define FBUFFER_LEN(fb)
Definition: fbuffer.h:56
#define FBUFFER_PTR(fb)
Definition: fbuffer.h:55
#define FORCE_UTF8(obj)
Definition: fbuffer.h:36
#define FBUFFER_INITIAL_LENGTH_DEFAULT
Definition: fbuffer.h:53
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
#define MEMCPY(p1, p2, type, n)
#define RSTRING_LEN(str)
#define StringValuePtr(v)
#define rb_str_new(str, len)
#define REALLOC_N(var, type, n)
__inline__ const void *__restrict__ size_t len
#define ALLOC_N(type, n)
#define RB_GC_GUARD(v)
void * memset(void *, int, size_t)
#define ALLOC(type)
void void ruby_xfree(void *)
Definition: gc.c:10183
unsigned long VALUE
Definition: ruby.h:102
unsigned long len
Definition: fbuffer.h:49
unsigned long initial_length
Definition: fbuffer.h:47
char * ptr
Definition: fbuffer.h:48
unsigned long capa
Definition: fbuffer.h:50