#include namespace Upp { #define LTIMING(x) // RTIMING(x) void ESC_count(EscEscape& e) { e = e[0].GetCount(); } void ESC_is_void(EscEscape& e) { e = e[0].IsVoid(); } void ESC_is_number(EscEscape& e) { e = e[0].IsNumber(); } void ESC_is_array(EscEscape& e) { e = e[0].IsArray(); } void ESC_is_map(EscEscape& e) { e = e[0].IsMap(); } void ESC_int(EscEscape& e) { if(e[0].IsNumber()) e = (int)e[0].GetNumber(); } void ESC_to_string(EscEscape& e) { e = e[0].ToString(); } void ESC_to_number(EscEscape& e) { if(e[0].IsArray()) { double d = ScanDouble((String)e[0]); if(!IsNull(d)) { if(d <= INT64_MAX && d >= INT64_MIN) e = ScanInt64((String)e[0]); else e = d; } } } void ESC_rand(EscEscape& e) { e = rand(); } void ESC_keys(EscEscape& e) { e.CheckMap(0); EscValue v; const VectorMap& m = e[0].GetMap(); for(int i = 0; i < m.GetCount(); i++) if(!m.IsUnlinked(i)) v.ArrayAdd(m.GetKey(i)); e = v; } void ESC_values(EscEscape& e) { e.CheckMap(0); EscValue v; const VectorMap& m = e[0].GetMap(); for(int i = 0; i < m.GetCount(); i++) if(!m.IsUnlinked(i)) v.ArrayAdd(m[i]); e = v; } void ESC_reverse(EscEscape& e) { e.CheckArray(0); const Vector& a = e[0].GetArray(); EscValue r; for(int i = a.GetCount() - 1; i >= 0; i--) r.ArrayAdd(a[i]); e = r; } struct EscCmp { Esc *esc; bool operator()(const EscValue& a, const EscValue& b) const { return esc->DoCompare(a, b, "< (sort)") < 0; } }; Vector EscGetSortOrder(EscEscape& e) { e.CheckArray(0); const Vector& va = e[0].GetArray(); EscCmp cmp; cmp.esc = &e.esc; return GetSortOrder(va, cmp); } void ESC_sort(EscEscape& e) { Vector so = EscGetSortOrder(e); EscValue r; for(int i = 0; i < so.GetCount(); i++) r.ArrayAdd(e[0].ArrayGet(so[i])); e = r; } void ESC_order(EscEscape& e) { Vector so = EscGetSortOrder(e); EscValue r; for(int i = 0; i < so.GetCount(); i++) r.ArrayAdd(so[i]); e = r; } // --------------------------- void ESC_mid(EscEscape& e) { e.CheckArray(0); int pos = e.Int(1); int count = e.Int(2); if(pos < 0 || pos + count > e[0].GetCount()) e.ThrowError("out of bounds in call to 'mid'"); e.ret_val = e[0].ArrayGet(pos, count); } void ESC_exists(EscEscape& e) { e.CheckMap(0); e = !e[0].MapGet(e[1]).IsVoid(); } struct ESC_FileOut : public EscHandle { FileStream file; void Put(EscEscape& e) { if(file) file.Put(e.Int(0)); } void PutLine(EscEscape& e) { if(file) file.PutLine(String(e[0])); } void Close(EscEscape& e) { if(file) file.Close(); } typedef ESC_FileOut CLASSNAME; ESC_FileOut(EscEscape& e, EscValue& v, int style) { file.Open(String(e[0]), style); v.Escape("Put(a)", this, THISBACK(Put)); v.Escape("PutLine(a)", this, THISBACK(PutLine)); v.Escape("Close()", this, THISBACK(Close)); } }; void ESC_OpenFileOut(EscEscape& e) { EscValue v; ESC_FileOut *f = new ESC_FileOut(e, v, FileStream::CREATE); if(f->file) e = v; } void ESC_OpenFileAppend(EscEscape& e) { EscValue v; ESC_FileOut *f = new ESC_FileOut(e, v, FileStream::APPEND); if(f->file) e = v; } struct ESC_FileIn : public EscHandle { FileIn file; void IsEof(EscEscape& e) { e = file.IsEof(); } void Get(EscEscape& e) { e = file.Get(); } void GetLine(EscEscape& e) { e = file.GetLine(); } void Close(EscEscape& e) { if(file) file.Close(); } typedef ESC_FileIn CLASSNAME; ESC_FileIn(EscEscape& e, EscValue& v) { file.Open(String(e[0])); v.Escape("IsEof()", this, THISBACK(IsEof)); v.Escape("Get()", this, THISBACK(Get)); v.Escape("GetLine()", this, THISBACK(GetLine)); v.Escape("Close()", this, THISBACK(Close)); } }; void ESC_OpenFileIn(EscEscape& e) { EscValue v; ESC_FileIn *f = new ESC_FileIn(e, v); if(f->file) e = v; } // --------------------------- bool IsDate(const EscValue& v) { return v.HasNumberField("year") && v.HasNumberField("month") && v.HasNumberField("day"); } bool IsTime(const EscValue& v) { return IsDate(v) && v.HasNumberField("hour") && v.HasNumberField("minute") && v.HasNumberField("second"); } void SIC_IsDate(EscEscape& e) { e = IsDate(e[0]); } void SIC_IsTime(EscEscape& e) { e = IsTime(e[0]); } void SIC_GetSysTime(EscEscape& e) { Time tm = GetSysTime(); EscValue v; v.MapSet("year", (int)tm.year); v.MapSet("month", (int)tm.month); v.MapSet("day", (int)tm.day); v.MapSet("hour", (int)tm.hour); v.MapSet("minute", (int)tm.minute); v.MapSet("second", (int)tm.second); e = v; } void ESC_ToLower(EscEscape& e) { String s = e[0]; e = ToLower(s); } void ESC_ToUpper(EscEscape& e) { String s = e[0]; e = ToUpper(s); } // --------------------------- void ESC_replace(EscEscape& e) { String str = e[0]; str.Replace(e[1], e[2]); e = str; } // --------------------------- void StdLib(ArrayMap& global) { Escape(global, "is_number(value)", ESC_is_number); Escape(global, "is_array(value)", ESC_is_array); Escape(global, "is_map(value)", ESC_is_map); Escape(global, "is_void(value)", ESC_is_void); Escape(global, "int(value)", ESC_int); Escape(global, "to_string(value)", ESC_to_string); Escape(global, "to_number(value)", ESC_to_number); Escape(global, "count(value)", ESC_count); Escape(global, "keys(map)", ESC_keys); Escape(global, "values(map)", ESC_values); Escape(global, "rand()", ESC_rand); Escape(global, "reverse(array)", ESC_reverse); Escape(global, "sort(array)", ESC_sort); Escape(global, "order(array)", ESC_order); Escape(global, "replace(str, find, replace)", ESC_replace); Escape(global, "ToUpper(value)", ESC_ToUpper); Escape(global, "ToLower(value)", ESC_ToLower); Escape(global, "len(x)", ESC_count); Escape(global, "mid(array, pos, count)", ESC_mid); Escape(global, "exists(map, key)", ESC_exists); Escape(global, "OpenFileOut(x)", ESC_OpenFileOut); Escape(global, "OpenFileAppend(x)", ESC_OpenFileOut); Escape(global, "OpenFileIn(x)", ESC_OpenFileIn); Escape(global, "GetSysTime()", SIC_GetSysTime); Escape(global, "IsDate(x)", SIC_IsDate); Escape(global, "IsTime(x)", SIC_IsTime); #define FN(fn) Escfn(global, #fn "(value)", [](EscEscape& e) { e = fn(e[0].GetNumber()); }); FN(sin) FN(cos) FN(tan) FN(asin) FN(acos) FN(atan) FN(sinh) FN(cosh) FN(tanh) FN(asinh) FN(acosh) FN(atanh) FN(exp) FN(log) FN(log10) FN(exp2) FN(log2) FN(sqrt) FN(cbrt) #undef FN Escfn(global, "pow(base, exponent)", [](EscEscape& e) { e = pow(e[0].GetNumber(), e[1].GetNumber()); }); Escfn(global, "atan2(a, b)", [](EscEscape& e) { e = atan2(e[0].GetNumber(), e[1].GetNumber()); }); } }