PageRenderTime 44ms CodeModel.GetById 23ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/string.go

http://github.com/feyeleanor/RubyGoLightly
Go | 183 lines | 158 code | 22 blank | 3 comment | 27 complexity | bb7573de22079d72498df2188209e19b MD5 | raw file
  1#include <alloca.h>
  2#include <stdarg.h>
  3#include <stdio.h>
  4
  5import (
  6	"bytes";
  7	"fmt";
  8	"tr";
  9)
 10
 11// symbol
 12
 13func TrSymbol_lookup(vm *RubyVM, name string) RubyObject {
 14	return vm.symbols[name] || TR_NIL;
 15}
 16
 17func TrSymbol_add(vm *RubyVM, name *string, id *RubyObject) {
 18	vm.symbols[name] = id;
 19}
 20
 21func TrSymbol_new(vm *RubyVM, str *string) RubyObject {
 22	id := TrSymbol_lookup(vm, str);
 23  
 24	if (!id) {
 25		s := Symbol{type: TR_T_Symbol, class: vm.classes[TR_T_Symbol], ivars: make(map[string] RubyObject), len: strlen(str), ptr: make([]byte, s.len + 1), interned: true};
 26		bytes.Copy(s.ptr, str[0:s.len - 1]);
 27		s.ptr[s.len] = '\0';
 28		id := s;
 29		TrSymbol_add(vm, s.ptr, id);
 30	}
 31	return id;
 32}
 33
 34func TrSymbol_to_s(vm *RubyVM, self *RubyObject) RubyObject {
 35	if !self.(String) && !self.(Symbol) {
 36		vm.throw_reason = TR_THROW_EXCEPTION;
 37		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
 38		return TR_UNDEF;
 39	}
 40	return TrString_new(vm, self.ptr, self.len);
 41}
 42
 43func TrSymbol_init(vm *RubyVM) {
 44	c := vm.classes[TR_T_Symbol] = Object_const_set(vm, vm.self, TrSymbol_new(vm, Symbol), newClass(vm, TrSymbol_new(vm, Symbol), vm.classes[TR_T_Object]));
 45	c.add_method(vm, TrSymbol_new(vm, "to_s"), newMethod(vm, (TrFunc *)TrSymbol_to_s, TR_NIL, 0));
 46}
 47
 48// string
 49
 50func TrString_to_s(vm *RubyVM, self *RubyObject) RubyObject {
 51	return self;
 52}
 53
 54func TrString_size(vm *RubyVM, self) RubyObject {
 55	if !self.(String) && !self.(Symbol) {
 56		vm.throw_reason = TR_THROW_EXCEPTION;
 57		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
 58		return TR_UNDEF;
 59	}
 60	return TR_INT2FIX(self.len);
 61}
 62
 63func TrString_new(vm *RubyVM, str *string, len size_t) RubyObject {
 64	s := String{type: TR_T_String, class: vm.classes[TR_T_String], ivars: make(map[string] RubyObject), len: len, ptr: make([]byte, s.len + 1)};
 65	bytes.Copy(s.ptr, str[0:s.len - 1]);
 66	s.ptr[s.len] = '\0';
 67	return s;
 68}
 69
 70func TrString_new2(vm *RubyVM, str *string) RubyObject {
 71	return TrString_new(vm, str, strlen(str));
 72}
 73
 74func TrString_new3(vm *RubyVM, len size_t) RubyObject {
 75	s := String{type: TR_T_String, class: vm.classes[TR_T_String], ivars: make(map[string] RubyObject), len: len, ptr: make([]byte, s.len + 1)};
 76	s.ptr[s.len] = '\0'
 77	return s;
 78}
 79
 80func TrString_add(vm *RubyVM, self, other *RubyObject) RubyObject {
 81	if !self.(String) && !self.(Symbol) {
 82		vm.throw_reason = TR_THROW_EXCEPTION;
 83		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
 84		return TR_UNDEF;
 85	}
 86	if !other.(String) && !other.(Symbol) {
 87		vm.throw_reason = TR_THROW_EXCEPTION;
 88		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + other));
 89		return TR_UNDEF;
 90	}
 91	return tr_sprintf(vm, "%s%s", self.ptr, other.ptr);
 92}
 93
 94func TrString_push(vm *RubyVM, self, other *RubyObject) RubyObject {
 95	if !self.(String) && !self.(Symbol) {
 96		vm.throw_reason = TR_THROW_EXCEPTION;
 97		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
 98		return TR_UNDEF;
 99	}
100	if !other.(String) && !other.(Symbol) {
101		vm.throw_reason = TR_THROW_EXCEPTION;
102		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + other));
103		return TR_UNDEF;
104	}
105	orginal_len := self.len;
106	self.len += other.len;
107	self.ptr := TR_REALLOC(self.ptr, self.len + 1);
108	memcpy(self.ptr + original_len, other.ptr, sizeof(char) * other.len);
109	self.ptr[self.len] = '\0';
110	return self;
111}
112
113func TrString_replace(vm *RubyVM, self, other *RubyObject) RubyObject {
114	if !self.(String) && !self.(Symbol) {
115		vm.throw_reason = TR_THROW_EXCEPTION;
116		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
117		return TR_UNDEF;
118	}
119	if !other.(String) && !other.(Symbol) {
120		vm.throw_reason = TR_THROW_EXCEPTION;
121		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + other));
122		return TR_UNDEF;
123	}
124	self.ptr, self.len = other.ptr, other.len;
125	return self;
126}
127
128func TrString_cmp(vm *RubyVM, self, other *RubyObject) RubyObject {
129	if (!other.(String)) return TR_INT2FIX(-1);
130	if !self.(String) && !self.(Symbol) {
131		vm.throw_reason = TR_THROW_EXCEPTION;
132		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
133		return TR_UNDEF;
134	}
135	return TR_INT2FIX(strcmp(self.ptr, other.ptr));
136}
137
138func TrString_substring(vm *RubyVM, self, start, len *RubyObject) RubyObject {
139	int s = TR_FIX2INT(start);
140	int l = TR_FIX2INT(len);
141	if !self.(String) && !self.(Symbol) {
142		vm.throw_reason = TR_THROW_EXCEPTION;
143		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
144		return TR_UNDEF;
145	}
146	if s < 0 || (s + l) > self.len { return TR_NIL; }
147	return TrString_new(vm, self.ptr + s, l);
148}
149
150func TrString_to_sym(vm *RubyVM, self *RubyObject) RubyObject {
151	if !self.(String) && !self.(Symbol) {
152		vm.throw_reason = TR_THROW_EXCEPTION;
153		vm.throw_value = TrException_new(vm, vm.cTypeError, TrString_new2(vm, "Expected " + self));
154		return TR_UNDEF;
155	}
156	return TrSymbol_new(vm, self.ptr);
157}
158
159// Uses variadic ... parameter which replaces the mechanism used by stdarg.h
160func tr_sprintf(vm *RubyVM, fmt *string, args ...) RubyObject {
161	arg va_list;
162	va_start(arg, fmt);
163	len := vsnprintf(NULL, 0, fmt, arg);
164	char *ptr = alloca(sizeof(char) * len);
165	va_end(arg);
166	va_start(arg, fmt);
167	vsprintf(ptr, fmt, arg);
168	va_end(arg);
169	str := TrString_new(vm, ptr, len);
170	return str;
171}
172
173func TrString_init(vm *RubyVM) {
174	c := vm.classes[TR_T_String] = Object_const_set(vm, vm.self, TrSymbol_new(vm, String), newClass(vm, TrSymbol_new(vm, String), vm.classes[TR_T_Object]));
175	c.add_method(vm, TrSymbol_new(vm, "to_s"), newMethod(vm, (TrFunc *)TrString_to_s, TR_NIL, 0));
176	c.add_method(vm, TrSymbol_new(vm, "to_sym"), newMethod(vm, (TrFunc *)TrString_to_sym, TR_NIL, 0));
177	c.add_method(vm, TrSymbol_new(vm, "size"), newMethod(vm, (TrFunc *)TrString_size, TR_NIL, 0));
178	c.add_method(vm, TrSymbol_new(vm, "replace"), newMethod(vm, (TrFunc *)TrString_replace, TR_NIL, 1));
179	c.add_method(vm, TrSymbol_new(vm, "substring"), newMethod(vm, (TrFunc *)ToString_substring, TR_NIL, 2));
180	c.add_method(vm, TrSymbol_new(vm, "+"), newMethod(vm, (TrFunc *)TrString_add, TR_NIL, 1));
181	c.add_method(vm, TrSymbol_new(vm, "<<"), newMethod(vm, (TrFunc *)TrString_push, TR_NIL, 1));
182	c.add_method(vm, TrSymbol_new(vm, "<=>"), newMethod(vm, (TrFunc *)TrString_cmp, TR_NIL, 1));
183}