Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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_PTR
16 #define RARRAY_PTR(ARRAY) RARRAY(ARRAY)->ptr
17 #endif
18 #ifndef RARRAY_LEN
19 #define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len
20 #endif
21 #ifndef RSTRING_PTR
22 #define RSTRING_PTR(string) RSTRING(string)->ptr
23 #endif
24 #ifndef RSTRING_LEN
25 #define RSTRING_LEN(string) RSTRING(string)->len
26 #endif
27
28 #ifdef HAVE_RUBY_ENCODING_H
29 #include "ruby/encoding.h"
30 #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
31 #else
32 #define FORCE_UTF8(obj)
33 #endif
34
35 /* We don't need to guard objects for rbx, so let's do nothing at all. */
36 #ifndef RB_GC_GUARD
37 #define RB_GC_GUARD(object)
38 #endif
39
40 typedef struct FBufferStruct {
41 unsigned long initial_length;
42 char *ptr;
43 unsigned long len;
44 unsigned long capa;
45 } FBuffer;
46
47 #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
48
49 #define FBUFFER_PTR(fb) (fb->ptr)
50 #define FBUFFER_LEN(fb) (fb->len)
51 #define FBUFFER_CAPA(fb) (fb->capa)
52 #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
53
54 static FBuffer *fbuffer_alloc(unsigned long initial_length);
55 static void fbuffer_free(FBuffer *fb);
56 static void fbuffer_clear(FBuffer *fb);
57 static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
58 #ifdef JSON_GENERATOR
59 static void fbuffer_append_long(FBuffer *fb, long number);
60 #endif
61 static void fbuffer_append_char(FBuffer *fb, char newchr);
62 #ifdef JSON_GENERATOR
63 static FBuffer *fbuffer_dup(FBuffer *fb);
64 static VALUE fbuffer_to_s(FBuffer *fb);
65 #endif
66
67 static FBuffer *fbuffer_alloc(unsigned long initial_length)
68 {
69 FBuffer *fb;
70 if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
71 fb = ALLOC(FBuffer);
72 memset((void *) fb, 0, sizeof(FBuffer));
73 fb->initial_length = initial_length;
74 return fb;
75 }
76
77 static void fbuffer_free(FBuffer *fb)
78 {
79 if (fb->ptr) ruby_xfree(fb->ptr);
80 ruby_xfree(fb);
81 }
82
83 static void fbuffer_clear(FBuffer *fb)
84 {
85 fb->len = 0;
86 }
87
88 static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
89 {
90 unsigned long required;
91
92 if (!fb->ptr) {
93 fb->ptr = ALLOC_N(char, fb->initial_length);
94 fb->capa = fb->initial_length;
95 }
96
97 for (required = fb->capa; requested > required - fb->len; required <<= 1);
98
99 if (required > fb->capa) {
100 REALLOC_N(fb->ptr, char, required);
101 fb->capa = required;
102 }
103 }
104
105 static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
106 {
107 if (len > 0) {
108 fbuffer_inc_capa(fb, len);
109 MEMCPY(fb->ptr + fb->len, newstr, char, len);
110 fb->len += len;
111 }
112 }
113
114 #ifdef JSON_GENERATOR
115 static void fbuffer_append_str(FBuffer *fb, VALUE str)
116 {
117 const char *newstr = StringValuePtr(str);
118 unsigned long len = RSTRING_LEN(str);
119
120 RB_GC_GUARD(str);
121
122 fbuffer_append(fb, newstr, len);
123 }
124 #endif
125
126 static void fbuffer_append_char(FBuffer *fb, char newchr)
127 {
128 fbuffer_inc_capa(fb, 1);
129 *(fb->ptr + fb->len) = newchr;
130 fb->len++;
131 }
132
133 #ifdef JSON_GENERATOR
134 static void freverse(char *start, char *end)
135 {
136 char c;
137
138 while (end > start) {
139 c = *end, *end-- = *start, *start++ = c;
140 }
141 }
142
143 static long fltoa(long number, char *buf)
144 {
145 static char digits[] = "0123456789";
146 long sign = number;
147 char* tmp = buf;
148
149 if (sign < 0) number = -number;
150 do *tmp++ = digits[number % 10]; while (number /= 10);
151 if (sign < 0) *tmp++ = '-';
152 freverse(buf, tmp - 1);
153 return tmp - buf;
154 }
155
156 static void fbuffer_append_long(FBuffer *fb, long number)
157 {
158 char buf[20];
159 unsigned long len = fltoa(number, buf);
160 fbuffer_append(fb, buf, len);
161 }
162
163 static FBuffer *fbuffer_dup(FBuffer *fb)
164 {
165 unsigned long len = fb->len;
166 FBuffer *result;
167
168 result = fbuffer_alloc(len);
169 fbuffer_append(result, FBUFFER_PAIR(fb));
170 return result;
171 }
172
173 static VALUE fbuffer_to_s(FBuffer *fb)
174 {
175 VALUE result = rb_str_new(FBUFFER_PAIR(fb));
176 fbuffer_free(fb);
177 FORCE_UTF8(result);
178 return result;
179 }
180 #endif
181 #endif
182