Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 00002 #ifndef _FBUFFER_H_ 00003 #define _FBUFFER_H_ 00004 00005 #include "ruby.h" 00006 00007 #ifndef RHASH_SIZE 00008 #define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries) 00009 #endif 00010 00011 #ifndef RFLOAT_VALUE 00012 #define RFLOAT_VALUE(val) (RFLOAT(val)->value) 00013 #endif 00014 00015 #ifndef RARRAY_PTR 00016 #define RARRAY_PTR(ARRAY) RARRAY(ARRAY)->ptr 00017 #endif 00018 #ifndef RARRAY_LEN 00019 #define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len 00020 #endif 00021 #ifndef RSTRING_PTR 00022 #define RSTRING_PTR(string) RSTRING(string)->ptr 00023 #endif 00024 #ifndef RSTRING_LEN 00025 #define RSTRING_LEN(string) RSTRING(string)->len 00026 #endif 00027 00028 #ifdef HAVE_RUBY_ENCODING_H 00029 #include "ruby/encoding.h" 00030 #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding()) 00031 #else 00032 #define FORCE_UTF8(obj) 00033 #endif 00034 00035 /* We don't need to guard objects for rbx, so let's do nothing at all. */ 00036 #ifndef RB_GC_GUARD 00037 #define RB_GC_GUARD(object) 00038 #endif 00039 00040 typedef struct FBufferStruct { 00041 unsigned long initial_length; 00042 char *ptr; 00043 unsigned long len; 00044 unsigned long capa; 00045 } FBuffer; 00046 00047 #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024 00048 00049 #define FBUFFER_PTR(fb) (fb->ptr) 00050 #define FBUFFER_LEN(fb) (fb->len) 00051 #define FBUFFER_CAPA(fb) (fb->capa) 00052 #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb) 00053 00054 static FBuffer *fbuffer_alloc(unsigned long initial_length); 00055 static void fbuffer_free(FBuffer *fb); 00056 static void fbuffer_clear(FBuffer *fb); 00057 static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len); 00058 #ifdef JSON_GENERATOR 00059 static void fbuffer_append_long(FBuffer *fb, long number); 00060 #endif 00061 static void fbuffer_append_char(FBuffer *fb, char newchr); 00062 #ifdef JSON_GENERATOR 00063 static FBuffer *fbuffer_dup(FBuffer *fb); 00064 static VALUE fbuffer_to_s(FBuffer *fb); 00065 #endif 00066 00067 static FBuffer *fbuffer_alloc(unsigned long initial_length) 00068 { 00069 FBuffer *fb; 00070 if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT; 00071 fb = ALLOC(FBuffer); 00072 memset((void *) fb, 0, sizeof(FBuffer)); 00073 fb->initial_length = initial_length; 00074 return fb; 00075 } 00076 00077 static void fbuffer_free(FBuffer *fb) 00078 { 00079 if (fb->ptr) ruby_xfree(fb->ptr); 00080 ruby_xfree(fb); 00081 } 00082 00083 static void fbuffer_clear(FBuffer *fb) 00084 { 00085 fb->len = 0; 00086 } 00087 00088 static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested) 00089 { 00090 unsigned long required; 00091 00092 if (!fb->ptr) { 00093 fb->ptr = ALLOC_N(char, fb->initial_length); 00094 fb->capa = fb->initial_length; 00095 } 00096 00097 for (required = fb->capa; requested > required - fb->len; required <<= 1); 00098 00099 if (required > fb->capa) { 00100 REALLOC_N(fb->ptr, char, required); 00101 fb->capa = required; 00102 } 00103 } 00104 00105 static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len) 00106 { 00107 if (len > 0) { 00108 fbuffer_inc_capa(fb, len); 00109 MEMCPY(fb->ptr + fb->len, newstr, char, len); 00110 fb->len += len; 00111 } 00112 } 00113 00114 #ifdef JSON_GENERATOR 00115 static void fbuffer_append_str(FBuffer *fb, VALUE str) 00116 { 00117 const char *newstr = StringValuePtr(str); 00118 unsigned long len = RSTRING_LEN(str); 00119 00120 RB_GC_GUARD(str); 00121 00122 fbuffer_append(fb, newstr, len); 00123 } 00124 #endif 00125 00126 static void fbuffer_append_char(FBuffer *fb, char newchr) 00127 { 00128 fbuffer_inc_capa(fb, 1); 00129 *(fb->ptr + fb->len) = newchr; 00130 fb->len++; 00131 } 00132 00133 #ifdef JSON_GENERATOR 00134 static void freverse(char *start, char *end) 00135 { 00136 char c; 00137 00138 while (end > start) { 00139 c = *end, *end-- = *start, *start++ = c; 00140 } 00141 } 00142 00143 static long fltoa(long number, char *buf) 00144 { 00145 static char digits[] = "0123456789"; 00146 long sign = number; 00147 char* tmp = buf; 00148 00149 if (sign < 0) number = -number; 00150 do *tmp++ = digits[number % 10]; while (number /= 10); 00151 if (sign < 0) *tmp++ = '-'; 00152 freverse(buf, tmp - 1); 00153 return tmp - buf; 00154 } 00155 00156 static void fbuffer_append_long(FBuffer *fb, long number) 00157 { 00158 char buf[20]; 00159 unsigned long len = fltoa(number, buf); 00160 fbuffer_append(fb, buf, len); 00161 } 00162 00163 static FBuffer *fbuffer_dup(FBuffer *fb) 00164 { 00165 unsigned long len = fb->len; 00166 FBuffer *result; 00167 00168 result = fbuffer_alloc(len); 00169 fbuffer_append(result, FBUFFER_PAIR(fb)); 00170 return result; 00171 } 00172 00173 static VALUE fbuffer_to_s(FBuffer *fb) 00174 { 00175 VALUE result = rb_str_new(FBUFFER_PAIR(fb)); 00176 fbuffer_free(fb); 00177 FORCE_UTF8(result); 00178 return result; 00179 } 00180 #endif 00181 #endif 00182