Mercurial > projects > dmdscript-tango
view dmdscript_tango/dstring.d @ 3:8363a4bf6a8f
rename package: dmdscript to dmdscript_tango
author | saaadel |
---|---|
date | Sun, 24 Jan 2010 18:33:05 +0200 |
parents | 55c2951c07be |
children |
line wrap: on
line source
/* Digital Mars DMDScript source code. * Copyright (c) 2000-2002 by Chromium Communications * D version Copyright (c) 2004-2006 by Digital Mars * All Rights Reserved * written by Walter Bright * www.digitalmars.com * Use at your own risk. There is no warranty, express or implied. * License for redistribution is by the GNU General Public License in gpl.txt. * * A binary, non-exclusive license for commercial use can be * purchased from www.digitalmars.com/dscript/buy.html. * * DMDScript is implemented in the D Programming Language, * www.digitalmars.com/d/ * * For a C++ implementation of DMDScript, including COM support, * see www.digitalmars.com/dscript/cppscript.html. */ module dmdscript_tango.dstring; import std.regexp; import std.utf; import std.c.stdlib; import std.c.string; import dmdscript_tango.script; import dmdscript_tango.dobject; import dmdscript_tango.dregexp; import dmdscript_tango.darray; import dmdscript_tango.value; import dmdscript_tango.threadcontext; import dmdscript_tango.dfunction; import dmdscript_tango.text; import dmdscript_tango.property; import dmdscript_tango.textgen.errmsgs; import dmdscript_tango.dnative; //alias script.tchar tchar; /* ===================== Dstring_fromCharCode ==================== */ void* Dstring_fromCharCode(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA 15.5.3.2 d_string s; for (size_t i = 0; i < arglist.length; i++) { Value* v; uint u; v = &arglist[i]; u = v.toUint16(); //writefln("string.fromCharCode(%x)", u); if (!std.utf.isValidDchar(u)) { ErrInfo errinfo; ret.putVundefined(); return pthis.RuntimeError(&errinfo, errmsgtbl[ERR_NOT_VALID_UTF], "String", "fromCharCode()", u); } std.utf.encode(s, u); //writefln("s[0] = %x, s = '%s'", s[0], s); } ret.putVstring(s); return null; } /* ===================== Dstring_constructor ==================== */ class Dstring_constructor : Dfunction { this(ThreadContext *tc) { super(1, tc.Dfunction_prototype); name = "String"; static NativeFunctionData nfd[] = [ { &TEXT_fromCharCode, &Dstring_fromCharCode, 1 }, ]; DnativeFunction.init(this, nfd, 0); } void *Construct(CallContext *cc, Value *ret, Value[] arglist) { // ECMA 15.5.2 d_string s; Dobject o; s = (arglist.length) ? arglist[0].toString() : TEXT_; o = new Dstring(s); ret.putVobject(o); return null; } void *Call(CallContext *cc, Dobject othis, Value* ret, Value[] arglist) { // ECMA 15.5.1 d_string s; s = (arglist.length) ? arglist[0].toString() : TEXT_; ret.putVstring(s); return null; } } /* ===================== Dstring_prototype_toString =============== */ void* Dstring_prototype_toString(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { //writef("Dstring.prototype.toString()\n"); // othis must be a String if (!othis.isClass(TEXT_String)) { ErrInfo errinfo; ret.putVundefined(); return pthis.RuntimeError(&errinfo, errmsgtbl[ERR_FUNCTION_WANTS_STRING], TEXT_toString, othis.classname); } else { Value *v; v = &(cast(Dstring)othis).value; Value.copy(ret, v); } return null; } /* ===================== Dstring_prototype_valueOf =============== */ void* Dstring_prototype_valueOf(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // Does same thing as String.prototype.toString() //writef("string.prototype.valueOf()\n"); // othis must be a String if (!othis.isClass(TEXT_String)) { ErrInfo errinfo; ret.putVundefined(); return pthis.RuntimeError(&errinfo, errmsgtbl[ERR_FUNCTION_WANTS_STRING], TEXT_valueOf, othis.classname); } else { Value *v; v = &(cast(Dstring)othis).value; Value.copy(ret, v); } return null; } /* ===================== Dstring_prototype_charAt =============== */ void* Dstring_prototype_charAt(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA 15.5.4.4 Value *v; int pos; // ECMA says pos should be a d_number, // but int should behave the same d_string s; d_string result; v = &othis.value; s = v.toString(); v = arglist.length ? &arglist[0] : &vundefined; pos = cast(int) v.toInteger(); result = TEXT_; if (pos >= 0) { size_t idx; while (1) { if (idx == s.length) break; if (pos == 0) { result = s[idx .. idx + std.utf.stride(s, idx)]; break; } idx += std.utf.stride(s, idx); pos--; } } ret.putVstring(result); return null; } /* ===================== Dstring_prototype_charCodeAt ============= */ void* Dstring_prototype_charCodeAt(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA 15.5.4.5 Value *v; int pos; // ECMA says pos should be a d_number, // but int should behave the same d_string s; uint len; d_number result; v = &othis.value; s = v.toString(); v = arglist.length ? &arglist[0] : &vundefined; pos = cast(int) v.toInteger(); result = d_number.nan; if (pos >= 0) { size_t idx; while (1) { assert(idx <= s.length); if (idx == s.length) break; if (pos == 0) { result = std.utf.decode(s, idx); break; } idx += std.utf.stride(s, idx); pos--; } } ret.putVnumber(result); return null; } /* ===================== Dstring_prototype_concat ============= */ void* Dstring_prototype_concat(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.6 d_string s; //writefln("Dstring.prototype.concat()"); s = othis.value.toString(); for (size_t a = 0; a < arglist.length; a++) s ~= arglist[a].toString(); ret.putVstring(s); return null; } /* ===================== Dstring_prototype_indexOf ============= */ void* Dstring_prototype_indexOf(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA 15.5.4.6 // String.prototype.indexOf(searchString, position) Value* v1; Value* v2; int pos; // ECMA says pos should be a d_number, // but I can't find a reason. d_string s; size_t sUCSdim; d_string searchString; int k; Value xx; xx.putVobject(othis); s = xx.toString(); sUCSdim = std.utf.toUCSindex(s, s.length); v1 = arglist.length ? &arglist[0] : &vundefined; v2 = (arglist.length >= 2) ? &arglist[1] : &vundefined; searchString = v1.toString(); pos = cast(int) v2.toInteger(); if (pos < 0) pos = 0; else if (pos > sUCSdim) pos = sUCSdim; if (searchString.length == 0) k = pos; else { pos = std.utf.toUTFindex(s, pos); k = std.string.find(s[pos .. length], searchString); if (k != -1) k = std.utf.toUCSindex(s, pos + k); } ret.putVnumber(k); return null; } /* ===================== Dstring_prototype_lastIndexOf ============= */ void* Dstring_prototype_lastIndexOf(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.8 // String.prototype.lastIndexOf(searchString, position) Value *v1; int pos; // ECMA says pos should be a d_number, // but I can't find a reason. d_string s; size_t sUCSdim; d_string searchString; int k; version (all) { { // This is the 'transferable' version Value *v; void *a; v = othis.Get(TEXT_toString); a = v.Call(cc, othis, ret, null); if (a) // if exception was thrown return a; s = ret.toString(); } } else { // the 'builtin' version s = othis.value.toString(); } sUCSdim = std.utf.toUCSindex(s, s.length); v1 = arglist.length ? &arglist[0] : &vundefined; searchString = v1.toString(); if (arglist.length >= 2) { d_number n; Value *v = &arglist[1]; n = v.toNumber(); if (std.math.isnan(n) || n > sUCSdim) pos = sUCSdim; else if (n < 0) pos = 0; else pos = cast(int) n; } else pos = sUCSdim; //writef("len = %d, p = '%ls'\n", len, p); //writef("pos = %d, sslen = %d, ssptr = '%ls'\n", pos, sslen, ssptr); //writefln("s = '%s', pos = %s, searchString = '%s'", s, pos, searchString); if (searchString.length == 0) k = pos; else { pos = std.utf.toUTFindex(s, pos); pos += searchString.length; if (pos > s.length) pos = s.length; k = std.string.rfind(s[0 .. pos], searchString); //writefln("s = '%s', pos = %s, searchString = '%s', k = %d", s, pos, searchString, k); if (k != -1) k = std.utf.toUCSindex(s, k); } ret.putVnumber(k); return null; } /* ===================== Dstring_prototype_localeCompare ============= */ void* Dstring_prototype_localeCompare(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.9 d_string s1; d_string s2; d_number n; Value *v; v = &othis.value; s1 = v.toString(); s2 = arglist.length ? arglist[0].toString() : vundefined.toString(); n = localeCompare(cc, s1, s2); ret.putVnumber(n); return null; } /* ===================== Dstring_prototype_match ============= */ void* Dstring_prototype_match(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.10 Dregexp r; Dobject o; if (arglist.length && !arglist[0].isPrimitive() && (o = arglist[0].toObject()).isDregexp()) { ; } else { Value regret; regret.putVobject(null); Dregexp.getConstructor().Construct(cc, ®ret, arglist); o = regret.object; } r = cast(Dregexp)o; if (r.global.dbool) { Darray a = new Darray; d_int32 n; d_int32 i; d_int32 lasti; i = 0; lasti = 0; for (n = 0; ; n++) { r.lastIndex.putVnumber(i); Dregexp.exec(r, ret, (&othis.value)[0 .. 1], EXEC_STRING); if (!ret.string) // if match failed { r.lastIndex.putVnumber(i); break; } lasti = i; i = cast(d_int32) r.lastIndex.toInt32(); if (i == lasti) // if no source was consumed i++; // consume a character a.Put(n, ret, 0); // a[n] = ret; } ret.putVobject(a); } else { Dregexp.exec(r, ret, (&othis.value)[0 .. 1], EXEC_ARRAY); } return null; } /* ===================== Dstring_prototype_replace ============= */ void* Dstring_prototype_replace(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.11 // String.prototype.replace(searchValue, replaceValue) d_string string; d_string searchString; d_string newstring; Value *searchValue; Value *replaceValue; Dregexp r; RegExp re; tchar[] replacement; d_string result; int m; int i; int lasti; std.regexp.regmatch_t[1] pmatch; Dfunction f; Value* v; v = &othis.value; string = v.toString(); searchValue = (arglist.length >= 1) ? &arglist[0] : &vundefined; replaceValue = (arglist.length >= 2) ? &arglist[1] : &vundefined; r = Dregexp.isRegExp(searchValue); f = Dfunction.isFunction(replaceValue); if (r) { int offset = 0; re = r.re; i = 0; result = string; r.lastIndex.putVnumber(0); for (;;) { Dregexp.exec(r, ret, (&othis.value)[0 .. 1], EXEC_STRING); if (!ret.string) // if match failed break; m = re.re_nsub; if (f) { Value* alist; alist = cast(Value *)alloca((m + 3) * Value.sizeof); assert(alist); alist[0].putVstring(ret.string); for (i = 0; i < m; i++) { alist[1 + i].putVstring( string[re.pmatch[1 + i].rm_so .. re.pmatch[1 + i].rm_eo]); } alist[m + 1].putVnumber(re.pmatch[0].rm_so); alist[m + 2].putVstring(string); f.Call(cc, f, ret, alist[0 .. m + 3]); replacement = ret.toString(); } else { newstring = replaceValue.toString(); replacement = re.replace(newstring); } int starti = re.pmatch[0].rm_so + offset; int endi = re.pmatch[0].rm_eo + offset; result = string[0 .. starti] ~ replacement ~ string[endi .. length]; if (re.attributes & RegExp.REA.global) { offset += replacement.length - (endi - starti); // If no source was consumed, consume a character lasti = i; i = cast(d_int32) r.lastIndex.toInt32(); if (i == lasti) { i++; r.lastIndex.putVnumber(i); } } else break; } } else { int match; searchString = searchValue.toString(); match = std.string.find(string, searchString); if (match >= 0) { pmatch[0].rm_so = match; pmatch[0].rm_eo = match + searchString.length; if (f) { Value[3] alist; alist[0].putVstring(searchString); alist[1].putVnumber(pmatch[0].rm_so); alist[2].putVstring(string); f.Call(cc, f, ret, alist); replacement = ret.toString(); } else { newstring = replaceValue.toString(); replacement = RegExp.replace3(newstring, string, pmatch); } result = string[0 .. match] ~ replacement ~ string[match + searchString.length .. length]; } else { result = string; } } ret.putVstring(result); return null; } /* ===================== Dstring_prototype_search ============= */ void* Dstring_prototype_search(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.12 Dregexp r; Dobject o; //writef("String.prototype.search()\n"); if (arglist.length && !arglist[0].isPrimitive() && (o = arglist[0].toObject()).isDregexp()) { ; } else { Value regret; regret.putVobject(null); Dregexp.getConstructor().Construct(cc, ®ret, arglist); o = regret.object; } r = cast(Dregexp)o; Dregexp.exec(r, ret, (&othis.value)[0 .. 1], EXEC_INDEX); return null; } /* ===================== Dstring_prototype_slice ============= */ void* Dstring_prototype_slice(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.13 d_int32 start; d_int32 end; d_int32 sUCSdim; d_string s; d_string r; Value *v; v = &othis.value; s = v.toString(); sUCSdim = std.utf.toUCSindex(s, s.length); switch (arglist.length) { case 0: start = 0; end = sUCSdim; break; case 1: start = arglist[0].toInt32(); end = sUCSdim; break; default: start = arglist[0].toInt32(); end = arglist[1].toInt32(); break; } if (start < 0) { start += sUCSdim; if (start < 0) start = 0; } else if (start >= sUCSdim) start = sUCSdim; if (end < 0) { end += sUCSdim; if (end < 0) end = 0; } else if (end >= sUCSdim) end = sUCSdim; if (start > end) end = start; start = toUTFindex(s, start); end = toUTFindex(s, end); r = s[start .. end]; ret.putVstring(r); return null; } /* ===================== Dstring_prototype_split ============= */ void* Dstring_prototype_split(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.14 // String.prototype.split(separator, limit) d_uint32 lim; d_uint32 p; d_uint32 q; d_uint32 e; Value* separator = &vundefined; Value* limit = &vundefined; Dregexp R; RegExp re; d_string rs; d_string T; d_string S; Darray A; int str; //writefln("Dstring_prototype_split()"); switch (arglist.length) { default: limit = &arglist[1]; case 1: separator = &arglist[0]; case 0: break; } Value *v; v = &othis.value; S = v.toString(); A = new Darray; if (limit.isUndefined()) lim = ~0u; else lim = limit.toUint32(); p = 0; R = Dregexp.isRegExp(separator); if (R) // regular expression { re = R.re; assert(re); rs = null; str = 0; } else // string { re = null; rs = separator.toString(); str = 1; } if (lim == 0) goto Lret; // ECMA v3 15.5.4.14 is specific: "If separator is undefined, then the // result array contains just one string, which is the this value // (converted to a string)." However, neither Javascript nor Jscript // do that, they regard an undefined as being the string "undefined". // We match Javascript/Jscript behavior here, not ECMA. // Uncomment for ECMA compatibility //if (!separator.isUndefined()) { //writefln("test1 S = '%s', rs = '%s'", S, rs); if (S.length) { L10: for (q = p; q != S.length; q++) { if (str) // string { if (q + rs.length <= S.length && !memcmp(S.ptr + q, rs.ptr, rs.length * tchar.sizeof)) { e = q + rs.length; if (e != p) { T = S[p .. q]; A.Put(cast(uint) A.length.number, T, 0); if (A.length.number == lim) goto Lret; p = e; goto L10; } } } else // regular expression { if (re.test(S, q)) { q = re.pmatch[0].rm_so; e = re.pmatch[0].rm_eo; if (e != p) { T = S[p .. q]; //writefln("S = '%s', T = '%s', p = %d, q = %d, e = %d\n", S, T, p, q, e); A.Put(cast(uint) A.length.number, T, 0); if (A.length.number == lim) goto Lret; p = e; for (uint i = 0; i < re.re_nsub; i++) { int so = re.pmatch[1 + i].rm_so; int eo = re.pmatch[1 + i].rm_eo; //writefln("i = %d, nsub = %s, so = %s, eo = %s, S.length = %s", i, re.re_nsub, so, eo, S.length); if (so != -1 && eo != -1) T = S[so .. eo]; else T = null; A.Put(cast(uint) A.length.number, T, 0); if (A.length.number == lim) goto Lret; } goto L10; } } } } T = S[p .. S.length]; A.Put(cast(uint) A.length.number, T, 0); goto Lret; } if (str) // string { if (rs.length <= S.length && S[0 .. rs.length] == rs[]) goto Lret; } else // regular expression { if (re.test(S, 0)) goto Lret; } } A.Put(0u, S, 0); Lret: ret.putVobject(A); return null; } /* ===================== Dstring_prototype_substr ============= */ void *dstring_substring(d_string s, size_t sUCSdim, d_number start, d_number end, Value *ret) { d_string sb; d_int32 sb_len; if (std.math.isnan(start)) start = 0; else if (start > sUCSdim) start = sUCSdim; else if (start < 0) start = 0; if (std.math.isnan(end)) end = 0; else if (end > sUCSdim) end = sUCSdim; else if (end < 0) end = 0; if (end < start) // swap { d_number t; t = start; start = end; end = t; } size_t st = std.utf.toUTFindex(s, cast(size_t)start); size_t en = std.utf.toUTFindex(s, cast(size_t)end); sb = s[st .. en]; ret.putVstring(sb); return null; } void* Dstring_prototype_substr(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // Javascript: TDG pg. 689 // String.prototype.substr(start, length) d_number start; d_number length; d_string s; s = othis.value.toString(); size_t sUCSdim = std.utf.toUCSindex(s, s.length); start = 0; length = 0; if (arglist.length >= 1) { start = arglist[0].toInteger(); if (start < 0) start = sUCSdim + start; if (arglist.length >= 2) { length = arglist[1].toInteger(); if (std.math.isnan(length) || length < 0) length = 0; } else length = sUCSdim - start; } return dstring_substring(s, sUCSdim, start, start + length, ret); } /* ===================== Dstring_prototype_substring ============= */ void* Dstring_prototype_substring(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA 15.5.4.9 // String.prototype.substring(start) // String.prototype.substring(start, end) d_number start; d_number end; d_string s; //writefln("String.prototype.substring()"); s = othis.value.toString(); size_t sUCSdim = std.utf.toUCSindex(s, s.length); start = 0; end = sUCSdim; if (arglist.length >= 1) { start = arglist[0].toInteger(); if (arglist.length >= 2) end = arglist[1].toInteger(); //writef("s = '%ls', start = %d, end = %d\n", s, start, end); } void* p = dstring_substring(s, sUCSdim, start, end, ret); return p; } /* ===================== Dstring_prototype_toLowerCase ============= */ enum CASE { Lower, Upper, LocaleLower, LocaleUpper }; void *tocase(Dobject othis, Value *ret, CASE caseflag) { d_string s; s = othis.value.toString(); switch (caseflag) { case CASE.Lower: s = std.string.tolower(s); break; case CASE.Upper: s = std.string.toupper(s); break; case CASE.LocaleLower: s = std.string.tolower(s); break; case CASE.LocaleUpper: s = std.string.toupper(s); break; default: assert(0); } ret.putVstring(s); return null; } void* Dstring_prototype_toLowerCase(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA 15.5.4.11 // String.prototype.toLowerCase() //writef("Dstring_prototype_toLowerCase()\n"); return tocase(othis, ret, CASE.Lower); } /* ===================== Dstring_prototype_toLocaleLowerCase ============= */ void* Dstring_prototype_toLocaleLowerCase(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.17 //writef("Dstring_prototype_toLocaleLowerCase()\n"); return tocase(othis, ret, CASE.LocaleLower); } /* ===================== Dstring_prototype_toUpperCase ============= */ void* Dstring_prototype_toUpperCase(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA 15.5.4.12 // String.prototype.toUpperCase() return tocase(othis, ret, CASE.Upper); } /* ===================== Dstring_prototype_toLocaleUpperCase ============= */ void* Dstring_prototype_toLocaleUpperCase(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.5.4.18 return tocase(othis, ret, CASE.LocaleUpper); } /* ===================== Dstring_prototype_anchor ============= */ void *dstring_anchor(Dobject othis, Value* ret, tchar[] tag, tchar[] name, Value[] arglist) { // For example: // "foo".anchor("bar") // produces: // <tag name="bar">foo</tag> d_string foo = othis.value.toString(); Value* va = arglist.length ? &arglist[0] : &vundefined; d_string bar = va.toString(); d_string s; s = "<" ~ tag ~ " " ~ name ~ "=\"" ~ bar ~ "\">" ~ foo ~ "</" ~ tag ~ ">"; ret.putVstring(s); return null; } void* Dstring_prototype_anchor(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // Non-standard extension // String.prototype.anchor(anchor) // For example: // "foo".anchor("bar") // produces: // <A NAME="bar">foo</A> return dstring_anchor(othis, ret, "A", "NAME", arglist); } void* Dstring_prototype_fontcolor(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_anchor(othis, ret, "FONT", "COLOR", arglist); } void* Dstring_prototype_fontsize(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_anchor(othis, ret, "FONT", "SIZE", arglist); } void* Dstring_prototype_link(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_anchor(othis, ret, "A", "HREF", arglist); } /* ===================== Dstring_prototype bracketing ============= */ /*************************** * Produce <tag>othis</tag> */ void *dstring_bracket(Dobject othis, Value* ret, char[] tag) { d_string foo = othis.value.toString(); d_string s; s = "<" ~ tag ~ ">" ~ foo ~ "</" ~ tag ~ ">"; ret.putVstring(s); return null; } void* Dstring_prototype_big(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // Non-standard extension // String.prototype.big() // For example: // "foo".big() // produces: // <BIG>foo</BIG> return dstring_bracket(othis, ret, "BIG"); } void* Dstring_prototype_blink(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "BLINK"); } void* Dstring_prototype_bold(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "B"); } void* Dstring_prototype_fixed(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "TT"); } void* Dstring_prototype_italics(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "I"); } void* Dstring_prototype_small(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "SMALL"); } void* Dstring_prototype_strike(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "STRIKE"); } void* Dstring_prototype_sub(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "SUB"); } void* Dstring_prototype_sup(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { return dstring_bracket(othis, ret, "SUP"); } /* ===================== Dstring_prototype ==================== */ class Dstring_prototype : Dstring { this(ThreadContext *tc) { super(tc.Dobject_prototype); Put(TEXT_constructor, tc.Dstring_constructor, DontEnum); static NativeFunctionData nfd[] = [ { &TEXT_toString, &Dstring_prototype_toString, 0 }, { &TEXT_valueOf, &Dstring_prototype_valueOf, 0 }, { &TEXT_charAt, &Dstring_prototype_charAt, 1 }, { &TEXT_charCodeAt, &Dstring_prototype_charCodeAt, 1 }, { &TEXT_concat, &Dstring_prototype_concat, 1 }, { &TEXT_indexOf, &Dstring_prototype_indexOf, 1 }, { &TEXT_lastIndexOf, &Dstring_prototype_lastIndexOf, 1 }, { &TEXT_localeCompare, &Dstring_prototype_localeCompare, 1 }, { &TEXT_match, &Dstring_prototype_match, 1 }, { &TEXT_replace, &Dstring_prototype_replace, 2 }, { &TEXT_search, &Dstring_prototype_search, 1 }, { &TEXT_slice, &Dstring_prototype_slice, 2 }, { &TEXT_split, &Dstring_prototype_split, 2 }, { &TEXT_substr, &Dstring_prototype_substr, 2 }, { &TEXT_substring, &Dstring_prototype_substring, 2 }, { &TEXT_toLowerCase, &Dstring_prototype_toLowerCase, 0 }, { &TEXT_toLocaleLowerCase, &Dstring_prototype_toLocaleLowerCase, 0 }, { &TEXT_toUpperCase, &Dstring_prototype_toUpperCase, 0 }, { &TEXT_toLocaleUpperCase, &Dstring_prototype_toLocaleUpperCase, 0 }, { &TEXT_anchor, &Dstring_prototype_anchor, 1 }, { &TEXT_fontcolor, &Dstring_prototype_fontcolor, 1 }, { &TEXT_fontsize, &Dstring_prototype_fontsize, 1 }, { &TEXT_link, &Dstring_prototype_link, 1 }, { &TEXT_big, &Dstring_prototype_big, 0 }, { &TEXT_blink, &Dstring_prototype_blink, 0 }, { &TEXT_bold, &Dstring_prototype_bold, 0 }, { &TEXT_fixed, &Dstring_prototype_fixed, 0 }, { &TEXT_italics, &Dstring_prototype_italics, 0 }, { &TEXT_small, &Dstring_prototype_small, 0 }, { &TEXT_strike, &Dstring_prototype_strike, 0 }, { &TEXT_sub, &Dstring_prototype_sub, 0 }, { &TEXT_sup, &Dstring_prototype_sup, 0 }, ]; DnativeFunction.init(this, nfd, DontEnum); } } /* ===================== Dstring ==================== */ class Dstring : Dobject { this(d_string s) { super(getPrototype()); classname = TEXT_String; Put(TEXT_length, std.utf.toUCSindex(s, s.length), DontEnum | DontDelete | ReadOnly); value.putVstring(s); } this(Dobject prototype) { super(prototype); classname = TEXT_String; Put(TEXT_length, 0, DontEnum | DontDelete | ReadOnly); value.putVstring(null); } static void init(ThreadContext *tc) { tc.Dstring_constructor = new Dstring_constructor(tc); tc.Dstring_prototype = new Dstring_prototype(tc); tc.Dstring_constructor.Put(TEXT_prototype, tc.Dstring_prototype, DontEnum | DontDelete | ReadOnly); } static Dfunction getConstructor() { ThreadContext *tc = ThreadContext.getThreadContext(); assert(tc); return tc.Dstring_constructor; } static Dobject getPrototype() { ThreadContext *tc = ThreadContext.getThreadContext(); assert(tc); return tc.Dstring_prototype; } }