result_t util_base::unique(v8::Local<v8::Value> v, bool sorted, v8::Local<v8::Array> &retVal) { Isolate* isolate = Isolate::current(); if (v->IsUndefined() || v->IsNull()) { retVal = v8::Array::New(isolate->m_isolate); return 0; } if (!v->IsArray()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Array> arr1 = v8::Array::New(isolate->m_isolate); v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(v); int32_t len = arr->Length(); QuickArray<v8::Local<v8::Value> > vals; int32_t i, j, n = 0; vals.resize(len); for (i = 0; i < len; i ++) { v8::Local<v8::Value> val = arr->Get(i); for (j = i - 1; j >= 0; j --) if (!vals[j].IsEmpty()) { if (val->StrictEquals(vals[j])) break; if (sorted) { j = -1; break; } } if (j < 0) vals[i] = val; } for (i = 0; i < len; i ++) if (!vals[i].IsEmpty()) arr1->Set(n++, vals[i]); retVal = arr1; return 0; }
std::string json_format(v8::Local<v8::Value> obj) { StringBuffer strBuffer; Isolate* isolate = Isolate::current(); QuickArray<_item> stk; QuickArray<v8::Local<v8::Object>> vals; v8::Local<v8::Value> v = obj; v8::Local<v8::String> mark_name = isolate->NewFromUtf8("_util_format_mark"); int32_t padding = 0; const int32_t tab_size = 2; _item *it = NULL; while (true) { if (v.IsEmpty()) strBuffer.append("undefined"); else if (v->IsUndefined() || v->IsNull() || v->IsDate() || v->IsBoolean() || v->IsBooleanObject()) strBuffer.append(*v8::String::Utf8Value(v)); else if (v->IsNumber() || v->IsNumberObject()) strBuffer.append(*v8::String::Utf8Value(v->ToNumber())); else if (v->IsString() || v->IsStringObject()) string_format(strBuffer, v); else if (v->IsRegExp()) { v8::Local<v8::RegExp> re = v8::Local<v8::RegExp>::Cast(v); v8::Local<v8::String> src = re->GetSource(); v8::RegExp::Flags flgs = re->GetFlags(); strBuffer.append('/'); strBuffer.append(*v8::String::Utf8Value(src)); strBuffer.append('/'); if (flgs & v8::RegExp::kIgnoreCase) strBuffer.append('i'); if (flgs & v8::RegExp::kGlobal) strBuffer.append('g'); if (flgs & v8::RegExp::kMultiline) strBuffer.append('m'); } else if (v->IsObject()) { do { v8::Local<v8::Object> obj = v->ToObject(); v8::Local<v8::Array> keys = obj->GetPropertyNames(); if (v->IsFunction() && keys->Length() == 0) { strBuffer.append("[Function]"); break; } obj_ptr<Buffer_base> buf = Buffer_base::getInstance(v); if (buf) { static char hexs[] = "0123456789abcdef"; std::string data; std::string s; int32_t len, i; buf->toString(data); len = (int32_t)data.length(); s.resize(len * 3 + 8); memcpy(&s[0], "<Buffer", 7); for (i = 0; i < len; i ++) { int32_t ch = (unsigned char)data[i]; s[i * 3 + 7] = ' '; s[i * 3 + 8] = hexs[ch >> 4]; s[i * 3 + 9] = hexs[ch & 0xf]; } s[i * 3 + 7] = '>'; strBuffer.append(s); break; } obj_ptr<Int64_base> int64Val = Int64_base::getInstance(v); if (int64Val) { std::string s; int64Val->toString(10, s); strBuffer.append(s); break; } v8::Local<v8::Value> mk = obj->GetHiddenValue(mark_name); if (!mk.IsEmpty()) { strBuffer.append("[Circular]"); break; } vals.append(obj); obj->SetHiddenValue(mark_name, obj); v8::Local<v8::Value> toArray = obj->Get(isolate->NewFromUtf8("toArray")); if (!IsEmpty(toArray) && toArray->IsFunction()) { v = v8::Local<v8::Function>::Cast(toArray)->Call(obj, 0, NULL); obj = v->ToObject(); } int32_t sz = (int32_t)stk.size(); if (v->IsArray()) { v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(v); int32_t len = array->Length(); if (len == 0) strBuffer.append("[]"); else { if (len == 1 && v->StrictEquals(array->Get(0))) strBuffer.append("[Circular]"); else { stk.resize(sz + 1); it = &stk[sz]; it->val = v; it->keys = array; it->len = len; strBuffer.append('['); padding += tab_size; } } break; } int32_t len = keys->Length(); if (len == 0) strBuffer.append("{}"); else { if (len == 1 && v->StrictEquals(obj->Get(keys->Get(0)))) strBuffer.append("[Circular]"); else { stk.resize(sz + 1); it = &stk[sz]; it->val = v; it->obj = obj; it->keys = keys; it->len = len; strBuffer.append('{'); padding += tab_size; } } } while (false); } if (it) { while (it && it->pos == it->len) { padding -= tab_size; newline(strBuffer, padding); strBuffer.append(it->obj.IsEmpty() ? ']' : '}'); int32_t sz = (int32_t)stk.size(); stk.resize(sz - 1); if (sz > 1) it = &stk[sz - 2]; else it = NULL; } if (!it) break; if (it->pos) strBuffer.append(','); newline(strBuffer, padding); v = it->keys->Get(it->pos ++); if (!it->obj.IsEmpty()) { TryCatch try_catch; string_format(strBuffer, v); strBuffer.append(": "); v = it->obj->Get(v); } } else break; } int32_t sz1 = (int32_t)vals.size(); int32_t i; for (i = 0; i < sz1; i ++) vals[i]->DeleteHiddenValue(mark_name); return strBuffer.str(); }
result_t util_base::intersection(const v8::FunctionCallbackInfo<v8::Value> &args, v8::Local<v8::Array> &retVal) { v8::Local<v8::Array> arr = v8::Array::New(Isolate::current()->m_isolate); int32_t argc = args.Length(); int32_t i, j, k, n = 0; if (argc > 0) { if (args[0]->IsUndefined() || args[0]->IsNull()) { retVal = arr; return 0; } for (j = 0; j < argc; j ++) if (!args[j]->IsArray()) return CHECK_ERROR(CALL_E_TYPEMISMATCH); v8::Local<v8::Array> base = v8::Local<v8::Array>::Cast(args[0]); int32_t len = base->Length(); int32_t left = len; QuickArray<v8::Local<v8::Value> > erase; erase.resize(len); for (i = 0; i < len; i ++) erase[i] = base->Get(i); for (i = 1; left > 0 && i < argc; i ++) { v8::Local<v8::Array> other = v8::Local<v8::Array>::Cast(args[i]); int32_t len1 = other->Length(); for (j = 0; left > 0 && j < len; j ++) if (!erase[j].IsEmpty()) { for (k = 0; k < len1; k ++) if (erase[j]->Equals(other->Get(k))) break; if (k == len1) { erase[j] = v8::Local<v8::Value>(); left --; } } } if (left) for (i = 0; i < len; i ++) if (!erase[i].IsEmpty()) { for (j = 0; j < i; j ++) if (!erase[j].IsEmpty() && erase[i]->Equals(erase[j])) break; if (j == i) arr->Set(n ++, erase[i]); } } retVal = arr; return 0; }