void ff::DumpDict(ff::StringRef name, const Dict &dict, Log *log, bool chain, bool debugOnly) { if (debugOnly && !GetThisModule().IsDebugBuild()) { return; } Log extraLog; Log &realLog = log ? *log : extraLog; realLog.TraceF(L"+- Options for: %s --\r\n", name.c_str()); Vector<String> names = dict.GetAllNames(chain, true, false); for (const String &key: names) { Value *value = dict.GetValue(key, chain); assert(value); String valueString; ValuePtr convertedValue; if (value->Convert(ff::Value::Type::String, &convertedValue)) { valueString = convertedValue->AsString(); } else if (value->Convert(ff::Value::Type::StringVector, &convertedValue)) { Vector<String> &strs = convertedValue->AsStringVector(); for (size_t i = 0; i < strs.Size(); i++) { valueString += String::format_new(L"\r\n| [%lu]: %s", i, strs[i].c_str()); } } else if (value->Convert(ff::Value::Type::Data, &convertedValue)) { valueString.format(L"<data[%lu]>", convertedValue->AsData()->GetSize()); } else { valueString = L"<data>"; } realLog.TraceF(L"| %s: %s\r\n", key.c_str(), valueString.c_str()); } realLog.Trace(L"+- Done --\r\n"); }
ff::String ff::Dict::GetString(ff::StringRef name, String defaultValue) const { Value *value = GetValue(name); if (value) { if (value->IsType(Value::Type::String)) { return value->AsString(); } else { ValuePtr newValue; if (value->Convert(Value::Type::String, &newValue)) { return newValue->AsString(); } } } return defaultValue; }
bool ff::Value::Convert(Type type, Value **ppValue) const { assertRetVal(ppValue, false); *ppValue = nullptr; if (type == GetType()) { *ppValue = GetAddRef(const_cast<Value *>(this)); return true; } wchar_t buf[256]; switch (GetType()) { case Type::Null: switch (type) { case Type::String: CreateString(String(L"null"), ppValue); break; } break; case Type::Bool: switch (type) { case Type::Double: CreateDouble(AsBool() ? 1.0 : 0.0, ppValue); break; case Type::Float: CreateFloat(AsBool() ? 1.0f : 0.0f, ppValue); break; case Type::Int: CreateInt(AsBool() ? 1 : 0, ppValue); break; case Type::String: CreateString(AsBool() ? String(L"true") : String(L"false"), ppValue); break; } break; case Type::Double: switch (type) { case Type::Bool: CreateBool(AsDouble() != 0, ppValue); break; case Type::Float: CreateFloat((float)AsDouble(), ppValue); break; case Type::Int: CreateInt((int)AsDouble(), ppValue); break; case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%g", AsDouble()); CreateString(String(buf), ppValue); break; } break; case Type::Float: switch (type) { case Type::Bool: CreateBool(AsFloat() != 0, ppValue); break; case Type::Double: CreateDouble((double)AsFloat(), ppValue); break; case Type::Int: CreateInt((int)AsFloat(), ppValue); break; case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%g", AsFloat()); CreateString(String(buf), ppValue); break; } break; case Type::Int: switch (type) { case Type::Bool: CreateBool(AsInt() != 0, ppValue); break; case Type::Double: CreateDouble((double)AsInt(), ppValue); break; case Type::Float: CreateFloat((float)AsInt(), ppValue); break; case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"%d", AsInt()); CreateString(String(buf), ppValue); break; } break; case Type::Point: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%d,%d)", AsPoint().x, AsPoint().y); CreateString(String(buf), ppValue); break; } break; case Type::PointF: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%g,%g)", AsPointF().x, AsPointF().y); CreateString(String(buf), ppValue); break; } break; case Type::Rect: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%d,%d,%d,%d)", AsRect().left, AsRect().top, AsRect().right, AsRect().bottom); CreateString(String(buf), ppValue); break; } break; case Type::RectF: switch (type) { case Type::String: _snwprintf_s(buf, _countof(buf), _TRUNCATE, L"(%g,%g,%g,%g)", AsRectF().left, AsRectF().top, AsRectF().right, AsRectF().bottom); CreateString(String(buf), ppValue); break; } break; case Type::String: switch (type) { case Type::Bool: if (AsString().empty() || AsString() == L"false" || AsString() == L"no" || AsString() == L"0") { CreateBool(false, ppValue); } else if (AsString() == L"true" || AsString() == L"yes" || AsString() == L"1") { CreateBool(true, ppValue); } break; case Type::Double: { const wchar_t *start = AsString().c_str(); wchar_t *end = nullptr; double val = wcstod(start, &end); if (end > start && !*end) { CreateDouble(val, ppValue); } } break; case Type::Float: { const wchar_t *start = AsString().c_str(); wchar_t *end = nullptr; double val = wcstod(start, &end); if (end > start && !*end) { CreateFloat((float)val, ppValue); } } break; case Type::Int: { const wchar_t *start = AsString().c_str(); wchar_t *end = nullptr; long val = wcstol(start, &end, 10); if (end > start && !*end) { CreateInt((int)val, ppValue); } } break; case Type::Guid: { GUID guid; if (StringToGuid(AsString(), guid)) { CreateGuid(guid, ppValue); } } break; } break; case Type::Object: switch (type) { case Type::Bool: CreateBool(AsObject() != nullptr, ppValue); break; } break; case Type::Guid: switch (type) { case Type::String: CreateString(StringFromGuid(AsGuid()), ppValue); break; } break; case Type::Data: switch (type) { case Type::SavedData: { ff::ComPtr<ff::ISavedData> savedData; if (ff::CreateLoadedDataFromMemory(AsData(), false, &savedData)) { CreateSavedData(savedData, ppValue); } } break; } break; case Type::SavedData: switch (type) { case Type::Data: { ff::ComPtr<ff::ISavedData> savedData; if (AsSavedData()->Clone(&savedData)) { ff::ComPtr<ff::IData> data = savedData->Load(); if (data) { CreateData(data, ppValue); } } } break; } break; case Type::Dict: switch (type) { case Type::Data: case Type::SavedData: case Type::SavedDict: { ff::ComPtr<ff::IData> data; ff::ComPtr<ff::ISavedData> savedData; if (ff::SaveDict(AsDict(), true, false, &data)) { if (type == Type::Data) { CreateData(data, ppValue); } else if (ff::CreateLoadedDataFromMemory(data, true, &savedData)) { if (type == Type::SavedData) { CreateSavedData(savedData, ppValue); } else { CreateSavedDict(savedData, ppValue); } } } } break; } break; case Type::SavedDict: switch (type) { case Type::Data: { ff::ComPtr<ff::ISavedData> savedData; if (AsSavedData()->Clone(&savedData)) { ff::ComPtr<ff::IData> data = savedData->Load(); if (data) { CreateData(data, ppValue); } } } break; case Type::SavedData: CreateSavedData(AsSavedData(), ppValue); break; case Type::Dict: { ff::ComPtr<ff::ISavedData> savedData; if (AsSavedData()->Clone(&savedData)) { ff::ComPtr<ff::IData> data = savedData->Load(); ff::ComPtr<ff::IDataReader> dataReader; Dict dict; if (data && ff::CreateDataReader(data, 0, &dataReader) && ff::LoadDict(dataReader, dict)) { CreateDict(std::move(dict), ppValue); } } } break; } break; case Type::Resource: AsResource()->GetValue()->Convert(type, ppValue); break; case Type::IntVector: switch (type) { case Type::Point: if (AsIntVector().Size() == 2) { PointInt point( AsIntVector().GetAt(0), AsIntVector().GetAt(1)); CreatePoint(point, ppValue); } break; case Type::Rect: if (AsIntVector().Size() == 4) { RectInt rect( AsIntVector().GetAt(0), AsIntVector().GetAt(1), AsIntVector().GetAt(2), AsIntVector().GetAt(3)); CreateRect(rect, ppValue); } break; } break; case Type::FloatVector: switch (type) { case Type::PointF: if (AsFloatVector().Size() == 2) { PointFloat point( AsFloatVector().GetAt(0), AsFloatVector().GetAt(1)); CreatePointF(point, ppValue); } break; case Type::RectF: if (AsFloatVector().Size() == 4) { RectFloat rect( AsFloatVector().GetAt(0), AsFloatVector().GetAt(1), AsFloatVector().GetAt(2), AsFloatVector().GetAt(3)); CreateRectF(rect, ppValue); } break; } break; case Type::ValueVector: switch (type) { case Type::Point: if (AsValueVector().Size() == 2) { ValuePtr newValues[2]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Int, &newValues[0]) && values[1]->Convert(Type::Int, &newValues[1])) { CreatePoint(PointInt(newValues[0]->AsInt(), newValues[1]->AsInt()), ppValue); } } break; case Type::PointF: if (AsValueVector().Size() == 2) { ValuePtr newValues[2]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Float, &newValues[0]) && values[1]->Convert(Type::Float, &newValues[1])) { CreatePointF(PointFloat(newValues[0]->AsFloat(), newValues[1]->AsFloat()), ppValue); } } break; case Type::Rect: if (AsValueVector().Size() == 4) { ValuePtr newValues[4]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Int, &newValues[0]) && values[1]->Convert(Type::Int, &newValues[1]) && values[2]->Convert(Type::Int, &newValues[2]) && values[3]->Convert(Type::Int, &newValues[3])) { CreateRect(RectInt( newValues[0]->AsInt(), newValues[1]->AsInt(), newValues[2]->AsInt(), newValues[3]->AsInt()), ppValue); } } break; case Type::RectF: if (AsValueVector().Size() == 4) { ValuePtr newValues[4]; const Vector<ValuePtr> &values = AsValueVector(); if (values[0]->Convert(Type::Float, &newValues[0]) && values[1]->Convert(Type::Float, &newValues[1]) && values[2]->Convert(Type::Float, &newValues[2]) && values[3]->Convert(Type::Float, &newValues[3])) { CreateRectF(RectFloat( newValues[0]->AsFloat(), newValues[1]->AsFloat(), newValues[2]->AsFloat(), newValues[3]->AsFloat()), ppValue); } } break; case Type::StringVector: { bool valid = true; Vector<String> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::String, &newValue); if (valid) { newValues.Push(newValue->AsString()); } else { break; } } if (valid) { CreateStringVector(std::move(newValues), ppValue); } } break; case Type::IntVector: { bool valid = true; Vector<int> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::Int, &newValue); if (valid) { newValues.Push(newValue->AsInt()); } else { break; } } if (valid) { CreateIntVector(std::move(newValues), ppValue); } } break; case Type::DoubleVector: { bool valid = true; Vector<double> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::Double, &newValue); if (valid) { newValues.Push(newValue->AsDouble()); } else { break; } } if (valid) { CreateDoubleVector(std::move(newValues), ppValue); } } break; case Type::FloatVector: { bool valid = true; Vector<float> newValues; const Vector<ValuePtr> &values = AsValueVector(); for (ValuePtr oldValue : values) { ValuePtr newValue; valid = oldValue->Convert(Type::Float, &newValue); if (valid) { newValues.Push(newValue->AsFloat()); } else { break; } } if (valid) { CreateFloatVector(std::move(newValues), ppValue); } } break; } break; } if (*ppValue) { return true; } return false; }