diff options
Diffstat (limited to 'jni/ruby/ext/json/fbuffer')
-rw-r--r-- | jni/ruby/ext/json/fbuffer/fbuffer.h | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/jni/ruby/ext/json/fbuffer/fbuffer.h b/jni/ruby/ext/json/fbuffer/fbuffer.h new file mode 100644 index 0000000..5a0a27c --- /dev/null +++ b/jni/ruby/ext/json/fbuffer/fbuffer.h @@ -0,0 +1,190 @@ + +#ifndef _FBUFFER_H_ +#define _FBUFFER_H_ + +#include "ruby.h" + +#ifndef RHASH_SIZE +#define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries) +#endif + +#ifndef RFLOAT_VALUE +#define RFLOAT_VALUE(val) (RFLOAT(val)->value) +#endif + +#ifndef RARRAY_PTR +#define RARRAY_PTR(ARRAY) RARRAY(ARRAY)->ptr +#endif +#ifndef RARRAY_LEN +#define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len +#endif +#ifndef RSTRING_PTR +#define RSTRING_PTR(string) RSTRING(string)->ptr +#endif +#ifndef RSTRING_LEN +#define RSTRING_LEN(string) RSTRING(string)->len +#endif + +#ifdef PRIsVALUE +# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) +# define RB_OBJ_STRING(obj) (obj) +#else +# define PRIsVALUE "s" +# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) +# define RB_OBJ_STRING(obj) StringValueCStr(obj) +#endif + +#ifdef HAVE_RUBY_ENCODING_H +#include "ruby/encoding.h" +#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding()) +#else +#define FORCE_UTF8(obj) +#endif + +/* We don't need to guard objects for rbx, so let's do nothing at all. */ +#ifndef RB_GC_GUARD +#define RB_GC_GUARD(object) +#endif + +typedef struct FBufferStruct { + unsigned long initial_length; + char *ptr; + unsigned long len; + unsigned long capa; +} FBuffer; + +#define FBUFFER_INITIAL_LENGTH_DEFAULT 1024 + +#define FBUFFER_PTR(fb) (fb->ptr) +#define FBUFFER_LEN(fb) (fb->len) +#define FBUFFER_CAPA(fb) (fb->capa) +#define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb) + +static FBuffer *fbuffer_alloc(unsigned long initial_length); +static void fbuffer_free(FBuffer *fb); +static void fbuffer_clear(FBuffer *fb); +static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len); +#ifdef JSON_GENERATOR +static void fbuffer_append_long(FBuffer *fb, long number); +#endif +static void fbuffer_append_char(FBuffer *fb, char newchr); +#ifdef JSON_GENERATOR +static FBuffer *fbuffer_dup(FBuffer *fb); +static VALUE fbuffer_to_s(FBuffer *fb); +#endif + +static FBuffer *fbuffer_alloc(unsigned long initial_length) +{ + FBuffer *fb; + if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT; + fb = ALLOC(FBuffer); + memset((void *) fb, 0, sizeof(FBuffer)); + fb->initial_length = initial_length; + return fb; +} + +static void fbuffer_free(FBuffer *fb) +{ + if (fb->ptr) ruby_xfree(fb->ptr); + ruby_xfree(fb); +} + +static void fbuffer_clear(FBuffer *fb) +{ + fb->len = 0; +} + +static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested) +{ + unsigned long required; + + if (!fb->ptr) { + fb->ptr = ALLOC_N(char, fb->initial_length); + fb->capa = fb->initial_length; + } + + for (required = fb->capa; requested > required - fb->len; required <<= 1); + + if (required > fb->capa) { + REALLOC_N(fb->ptr, char, required); + fb->capa = required; + } +} + +static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len) +{ + if (len > 0) { + fbuffer_inc_capa(fb, len); + MEMCPY(fb->ptr + fb->len, newstr, char, len); + fb->len += len; + } +} + +#ifdef JSON_GENERATOR +static void fbuffer_append_str(FBuffer *fb, VALUE str) +{ + const char *newstr = StringValuePtr(str); + unsigned long len = RSTRING_LEN(str); + + RB_GC_GUARD(str); + + fbuffer_append(fb, newstr, len); +} +#endif + +static void fbuffer_append_char(FBuffer *fb, char newchr) +{ + fbuffer_inc_capa(fb, 1); + *(fb->ptr + fb->len) = newchr; + fb->len++; +} + +#ifdef JSON_GENERATOR +static void freverse(char *start, char *end) +{ + char c; + + while (end > start) { + c = *end, *end-- = *start, *start++ = c; + } +} + +static long fltoa(long number, char *buf) +{ + static char digits[] = "0123456789"; + long sign = number; + char* tmp = buf; + + if (sign < 0) number = -number; + do *tmp++ = digits[number % 10]; while (number /= 10); + if (sign < 0) *tmp++ = '-'; + freverse(buf, tmp - 1); + return tmp - buf; +} + +static void fbuffer_append_long(FBuffer *fb, long number) +{ + char buf[20]; + unsigned long len = fltoa(number, buf); + fbuffer_append(fb, buf, len); +} + +static FBuffer *fbuffer_dup(FBuffer *fb) +{ + unsigned long len = fb->len; + FBuffer *result; + + result = fbuffer_alloc(len); + fbuffer_append(result, FBUFFER_PAIR(fb)); + return result; +} + +static VALUE fbuffer_to_s(FBuffer *fb) +{ + VALUE result = rb_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb)); + fbuffer_free(fb); + FORCE_UTF8(result); + return result; +} +#endif +#endif |