//---------------------------------------------------------------------- // 構造体比較関数 bool ScriptsAdd::equalStruct(tTJSVariant v1, tTJSVariant v2) { // タイプがオブジェクトなら特殊判定 if (v1.Type() == tvtObject && v2.Type() == tvtObject) { if (v1.AsObjectNoAddRef() == v2.AsObjectNoAddRef()) return true; tTJSVariantClosure &o1 = v1.AsObjectClosureNoAddRef(); tTJSVariantClosure &o2 = v2.AsObjectClosureNoAddRef(); // 関数どうしなら特別扱いで関数比較 if (o1.IsInstanceOf(0, NULL, NULL, L"Function", NULL)== TJS_S_TRUE && o2.IsInstanceOf(0, NULL, NULL, L"Function", NULL)== TJS_S_TRUE) return v1.DiscernCompare(v2); // Arrayどうしなら全項目を比較 if (o1.IsInstanceOf(0, NULL, NULL, L"Array", NULL)== TJS_S_TRUE && o2.IsInstanceOf(0, NULL, NULL, L"Array", NULL)== TJS_S_TRUE) { // 長さが一致していなければ比較失敗 tTJSVariant o1Count, o2Count; (void)o1.PropGet(0, L"count", &countHint, &o1Count, NULL); (void)o2.PropGet(0, L"count", &countHint, &o2Count, NULL); if (! o1Count.DiscernCompare(o2Count)) return false; // 全項目を順番に比較 tjs_int count = o1Count; tTJSVariant o1Val, o2Val; for (tjs_int i = 0; i < count; i++) { (void)o1.PropGetByNum(TJS_IGNOREPROP, i, &o1Val, NULL); (void)o2.PropGetByNum(TJS_IGNOREPROP, i, &o2Val, NULL); if (! equalStruct(o1Val, o2Val)) return false; } return true; } // Dictionaryどうしなら全項目を比較 if (o1.IsInstanceOf(0, NULL, NULL, L"Dictionary", NULL)== TJS_S_TRUE && o2.IsInstanceOf(0, NULL, NULL, L"Dictionary", NULL)== TJS_S_TRUE) { // 項目数が一致していなければ比較失敗 tjs_int o1Count, o2Count; (void)o1.GetCount(&o1Count, NULL, NULL, NULL); (void)o2.GetCount(&o2Count, NULL, NULL, NULL); if (o1Count != o2Count) return false; // 全項目を順番に比較 DictMemberCompareCaller *caller = new DictMemberCompareCaller(o2); tTJSVariantClosure closure(caller); tTJSVariant(o1.EnumMembers(TJS_IGNOREPROP, &closure, NULL)); bool result = caller->match; caller->Release(); return result; } } return v1.DiscernCompare(v2); }
// 実行 bool exec(iTJSDispatch2 *obj, tTVPWindowMessage *message) { switch (receiver.Type()) { case tvtObject: { tTJSVariant result; tTJSVariant wparam = (tjs_int)message->WParam; tTJSVariant lparam = (tjs_int)message->LParam; tTJSVariant *p[] = {&userData, &wparam, &lparam}; receiver.AsObjectClosureNoAddRef().FuncCall(0, NULL, NULL, &result, 3, p, NULL); return (int)result != 0; } break; case tvtString: { tTJSVariant result; tTJSVariant wparam = (tjs_int)message->WParam; tTJSVariant lparam = (tjs_int)message->LParam; tTJSVariant *p[] = {&userData, &wparam, &lparam}; obj->FuncCall(0, receiver.GetString(), NULL, &result, 3, p, obj); return (int)result != 0; } break; case tvtInteger: { NativeReceiver receiverNative = (NativeReceiver)(tjs_int)receiver; return receiverNative(obj, (void*)(tjs_int)userData, message); } break; } return false; }
/** * Date クラスの時刻をファイル時刻に変換 * @param restore 参照先(Dateクラスインスタンス) * @param filetime ファイル時刻結果格納先 * @return 取得できたかどうか */ static bool restoreDate(tTJSVariant &restore, FILETIME &filetime) { if (restore.Type() != tvtObject) return false; iTJSDispatch2 *date = restore.AsObjectNoAddRef(); if (!date) return false; tTJSVariant result; if (dateGetTime->FuncCall(0, NULL, NULL, &result, 0, NULL, date) != TJS_S_OK) return false; tjs_uint64 ft = result.AsInteger(); ft *= 10000; ft += 0x19DB1DED53E8000; filetime.dwLowDateTime = (DWORD)( ft & 0xFFFFFFFF); filetime.dwHighDateTime = (DWORD)((ft >> 32) & 0xFFFFFFFF); return true; }
//---------------------------------------------------------------------- // 構造体比較関数 tTJSVariant ScriptsAdd::clone(tTJSVariant obj) { // タイプがオブジェクトなら細かく判定 if (obj.Type() == tvtObject) { tTJSVariantClosure &o1 = obj.AsObjectClosureNoAddRef(); // Arrayの複製 if (o1.IsInstanceOf(0, NULL, NULL, L"Array", NULL)== TJS_S_TRUE) { iTJSDispatch2 *array = TJSCreateArrayObject(); tTJSVariant o1Count; (void)o1.PropGet(0, L"count", &countHint, &o1Count, NULL); tjs_int count = o1Count; tTJSVariant val; tTJSVariant *args[] = {&val}; for (tjs_int i = 0; i < count; i++) { (void)o1.PropGetByNum(TJS_IGNOREPROP, i, &val, NULL); val = ScriptsAdd::clone(val); static tjs_uint addHint = 0; (void)array->FuncCall(0, TJS_W("add"), &addHint, 0, 1, args, array); } tTJSVariant result(array, array); array->Release(); return result; } // Dictionaryの複製 if (o1.IsInstanceOf(0, NULL, NULL, L"Dictionary", NULL)== TJS_S_TRUE) { iTJSDispatch2 *dict = TJSCreateDictionaryObject(); DictMemberCloneCaller *caller = new DictMemberCloneCaller(dict); tTJSVariantClosure closure(caller); o1.EnumMembers(TJS_IGNOREPROP, &closure, NULL); caller->Release(); tTJSVariant result(dict, dict); dict->Release(); return result; } // cloneメソッドの呼び出しに成功すればそれを返す tTJSVariant result; static tjs_uint cloneHint = 0; if (o1.FuncCall(0, L"clone", &cloneHint, &result, 0, NULL, NULL)== TJS_S_TRUE) { return result; } } return obj; }
void copy(tTJSVariant v) { if (!buffer) TVPThrowExceptionMessage(TJS_W("LongExposure.copy: not initialized")); size_t curw = 0, curh = 0; if (!GetLayerSize(self, curw, curh)) TVPThrowExceptionMessage(TJS_W("LongExposure.copy: invalid layer image")); if (curw != width || curh != height) TVPThrowExceptionMessage(TJS_W("LongExposure.copy: invalid layer size")); BYTE *ptr = 0; long pitch = 0; if (!GetLayerImageForWrite(self, ptr, pitch)) TVPThrowExceptionMessage(TJS_W("LongExposure.copy: invalid layer image")); MinMaxRGBA m; switch (v.Type()) { case tvtVoid: if (!_stat(m)) TVPThrowExceptionMessage(TJS_W("LongExposure.copy: stat failed")); break; case tvtObject: { ncbPropAccessor rdic(v); if (rdic.IsValid()) { m._min.r = rdic.getIntValue(TJS_W("min_r")); m._min.g = rdic.getIntValue(TJS_W("min_g")); m._min.b = rdic.getIntValue(TJS_W("min_b")); m._min.a = rdic.getIntValue(TJS_W("min_a")); m._max.r = rdic.getIntValue(TJS_W("max_r")); m._max.g = rdic.getIntValue(TJS_W("max_g")); m._max.b = rdic.getIntValue(TJS_W("max_b")); m._max.a = rdic.getIntValue(TJS_W("max_a")); } } break; } for (size_t y = 0; y < height; y++) { const DWORD* r = buffer + width*4 * y; BYTE* w = ptr + pitch * y; for (size_t x = 0; x < width; x++) { *w++ = m.getNormalizeB(*r++); *w++ = m.getNormalizeG(*r++); *w++ = m.getNormalizeR(*r++); *w++ = m.getNormalizeA(*r++); } } }
static void getVariantString(tTJSVariant &var, IWriter *writer) { switch(var.Type()) { case tvtVoid: writer->write(L"void"); break; case tvtObject: { iTJSDispatch2 *obj = var.AsObjectNoAddRef(); if (obj == NULL) { writer->write(L"null"); } else if (obj->IsInstanceOf(TJS_IGNOREPROP,NULL,NULL,L"Array",obj) == TJS_S_TRUE) { getArrayString(obj, writer); } else { getDictString(obj, writer); } } break; case tvtString: quoteString(var.GetString(), writer); break; case tvtOctet: quoteOctet(var.AsOctetNoAddRef(), writer); break; case tvtInteger: writer->write(L"int "); writer->write((tTVInteger)var); break; case tvtReal: writer->write(L"real "); writer->write((tTVReal)var); break; default: writer->write(L"void"); break; }; }
/** * バイアント値を格納する */ void tTJSBinarySerializer::PutVariant( tTJSBinaryStream* stream, tTJSVariant& v ) { tTJSVariantType type = v.Type(); switch( type ) { case tvtVoid: { tjs_uint8 tmp[1]; tmp[0] = TYPE_VOID; stream->Write( tmp, sizeof(tmp) ); break; } case tvtObject: break; /* { iTJSDispatch2* obj = v.AsObjectNoAddRef(); iTJSDispatch2* objthis = v.AsObjectThisNoAddRef(); if( obj == NULL && objthis == NULL ) { Put( TYPE_NIL ); } else { SaveStructured } break; } */ case tvtString: PutString( stream, v.AsStringNoAddRef() ); break; case tvtOctet: PutOctet( stream, v.AsOctetNoAddRef() ); break; case tvtInteger: PutInteger( stream, v.AsInteger() ); break; case tvtReal: PutDouble( stream, v.AsReal() ); break; default: break; } }
virtual tjs_error TJS_INTF_METHOD FuncCall( // function invocation tjs_uint32 flag, // calling flag const tjs_char * membername,// member name ( NULL for a default member ) tjs_uint32 *hint, // hint for the member name (in/out) tTJSVariant *result, // result tjs_int numparams, // number of parameters tTJSVariant **param, // parameters iTJSDispatch2 *objthis // object as "this" ) { breakResult.Clear(); if (numparams > 1) { if ((int)*param[1] != TJS_HIDDENMEMBER) { paramList[0] = param[0]; paramList[1] = param[2]; (void)func->FuncCall(0, NULL, NULL, &breakResult, paramCount, paramList, functhis); } } if (result) { *result = breakResult.Type() == tvtVoid; } return TJS_S_OK; }
//--------------------------------------------------------------------------- tTJSString TJSVariantToReadableString(const tTJSVariant &val, tjs_int maxlen) { // convert given variant to human-readable string // ( eg. "(string)\"this is a\\nstring\"" ) tTJSVariantType type = val.Type(); switch(type) { case tvtVoid: { tTJSString str(TJS_W("(void)")); TJSTrimStringLength(str, maxlen); return str; } case tvtInteger: { tTJSString str(TJS_W("(int)")); str += (tTJSString)val; TJSTrimStringLength(str, maxlen); return str; } case tvtReal: { tTJSString str(TJS_W("(real)")); str += (tTJSString)val; TJSTrimStringLength(str, maxlen); return str; } case tvtString: { tTJSString str(TJS_W("(string)\"")); str += ttstr(val).EscapeC(); str += TJS_W("\""); TJSTrimStringLength(str, maxlen); return str; } case tvtOctet: { // TODO: octet conversion tTJSString str(TJS_W("(octet)<% ")); tTJSVariantString * s = TJSOctetToListString(val.AsOctetNoAddRef()); try { str += s; } catch(...) { if(s) s->Release(); throw; } if(s) s->Release(); str += TJS_W(" %>"); TJSTrimStringLength(str, maxlen); return str; } case tvtObject: { tTJSString str(TJS_W("(object)")); try { str += ttstr(val); } catch(...) { } TJSTrimStringLength(str, maxlen); return str; } } return TJS_W(""); }
//--------------------------------------------------------------------------- tTJSString TJSVariantToExpressionString(const tTJSVariant &val) { // convert given variant to string which can be interpret as an expression. // this function does not convert objects ( returns empty string ) tTJSVariantType type = val.Type(); switch(type) { case tvtVoid: { return TJS_W("void"); } case tvtInteger: { return ttstr(val); } case tvtReal: { tTJSString str; tTJSVariantString *s = TJSRealToHexString(val.AsReal()); try { str = s; } catch(...) { if(s) s->Release(); throw; } if(s) s->Release(); return str + TJS_W(" /" "* ") + ttstr(val) + TJS_W(" *" "/"); } case tvtString: { tTJSString str(TJS_W("\"")); str += ttstr(val).EscapeC(); str += TJS_W("\""); return str; } case tvtOctet: { tTJSString str(TJS_W("<% ")); tTJSVariantString * s = TJSOctetToListString(val.AsOctetNoAddRef()); try { str += s; } catch(...) { if(s) s->Release(); throw; } if(s) s->Release(); str += TJS_W(" %>"); return str; } case tvtObject: { return TJS_W(""); } } return TJS_W(""); }
/** * tTJSVariant を VARIANT に格納する * @param result 格納先 * @param variant 格納元 */ void IDispatchWrapper::storeVariant(VARIANT &result, tTJSVariant &variant) { VariantClear(&result); switch (variant.Type()) { case tvtVoid: //log(L"void"); break; case tvtObject: // オブジェクト //log(L"object"); { switch (variant.Type()) { case tvtObject: V_VT(&result) = VT_DISPATCH; V_DISPATCH(&result) = new IDispatchWrapper(variant.AsObjectNoAddRef()); break; default: V_VT(&result) = VT_NULL; break; } } break; case tvtString: //log(L"string"); // 文字列 V_VT(&result) = VT_BSTR; V_BSTR(&result) = SysAllocString(variant.GetString()); break; case tvtOctet: //log(L"octet"); // オクテット列 { tTJSVariantOctet *octet = variant.AsOctetNoAddRef(); if (octet) { SAFEARRAY *psa; SAFEARRAYBOUND sabound; sabound.lLbound = 0; sabound.cElements = octet->GetLength(); if ((psa = SafeArrayCreate(VT_UI1, 1, &sabound))) { // データをコピーする unsigned char *p; if (SUCCEEDED(SafeArrayAccessData(psa, (LPVOID*)&p))) { memcpy(p, octet->GetData(), octet->GetLength()); SafeArrayUnaccessData(psa); V_VT(&result) = VT_ARRAY | VT_UI1; V_ARRAY(&result) = psa; } else { SafeArrayDestroy(psa); } } else { // メモリ不足例外 } } } break; case tvtInteger: // COM は 64bit をサポートしていない!! // ということで COM に渡す引数で整数値は 32bit を超えないように注意すること(涙) //log(L"integer"); V_VT(&result) = VT_I4; V_I4(&result) = (int)(variant); break; case tvtReal: //log(L"real"); V_VT(&result) = VT_R8; V_R8(&result) = (double)(variant); break; } }