From: Josef 'Jupp' Schugt Date: 2003-06-17T05:59:34+09:00 Subject: Re: Hispeed String concat Saluton! * Michael Neumann; 2003-06-13, 23:05 UTC: > Why not make Storage a class, so you can have more than one? Your > current implementation does not allow this. Done. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # EXAMPLE of using 'Storage': require 'Storage' # Require library s = Storage.new(3) # s is to hold 3 chars s.append('foo') # append 'foo' to s s.append('bar') # append 'bar' to s (s grows to hold text) s.append('baz') # append 'baz' to s (s grows to hold text) puts s.to_s # prints 'foobarbaz' s.resize(6) # shrink s to hold 6 chars puts s.to_s # prints 'foobar' s.flush # flushes content of s puts s.to_s.length # 0 puts s.capacity # 6 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #include #include VALUE cStorage; typedef struct { char *start, *end; int capacity; } mem; static VALUE freemem(mem *m) { free(m->start); free(m); return Qnil; } VALUE new(VALUE class, VALUE size) { int n; mem *m = ALLOC(mem); VALUE data; Check_Type(size, T_FIXNUM); *(m->end = m->start = ALLOC_N(char, (n = NUM2ULONG(size)) + 1)) = '\0'; m->capacity = n; data = Data_Wrap_Struct(class, NULL, freemem, m); rb_obj_call_init(data, 0, NULL); return data; } static VALUE append(VALUE self, VALUE text) { mem *m; char *s, *t; int old, plus, need; Data_Get_Struct(self, mem, m); if ((need = (plus = strlen(s = STR2CSTR(text))) + (old = m->end - (t = m->start))) >= m->capacity) { REALLOC_N(m->start, char, (m->capacity = need) + 1); if (t != m->start) m->end = m->start + old; } strcpy(m->end, s); m->end += plus; return Qnil; } static VALUE resize(VALUE self, VALUE size) { mem *m; int n, len; char *s; Data_Get_Struct(self, mem, m); Check_Type(size, T_FIXNUM); len = m->end - (s = m->start); REALLOC_N(m->start, char, (m->capacity = n = NUM2ULONG(size)) + 1); if (s != m->start) m->end = m->start + ((n < len) ? n : len); *(m->start + n) = '\0'; return Qnil; } static VALUE flush(VALUE self) { mem *m; Data_Get_Struct(self, mem, m); *(m->end = m->start) = '\0'; return Qnil; } static VALUE to_s(VALUE self) { mem *m; Data_Get_Struct(self, mem, m); return rb_str_new2(m->start); } static VALUE capacity(VALUE self) { mem *m; Data_Get_Struct(self, mem, m); return INT2NUM(m->capacity); } void Init_Storage() { cStorage = rb_define_class("Storage", rb_cObject); rb_define_singleton_method(cStorage, "new", new, 1); rb_define_method(cStorage, "append", append, 1); rb_define_method(cStorage, "to_s", to_s, 0); rb_define_method(cStorage, "resize", resize, 1); rb_define_method(cStorage, "flush", flush, 0); rb_define_method(cStorage, "capacity", capacity, 0); } -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Gis, Josef 'Jupp' Schugt