AtObj AtlasObject::LoadFromJSON(JSContext* cx, const std::string& json)
{
	// Convert UTF8 to UTF16
	wxString jsonW(json.c_str(), wxConvUTF8);
	size_t json16len;
	wxCharBuffer json16 = wxMBConvUTF16().cWC2MB(jsonW.c_str(), jsonW.Length(), &json16len);

	jsval vp = JSVAL_NULL;
	JSONParser* parser = JS_BeginJSONParse(cx, &vp);
	if (!parser)
	{
		wxLogError(_T("ParseJSON failed to begin"));
		return AtObj();
	}

	if (!JS_ConsumeJSONText(cx, parser, reinterpret_cast<const jschar*>(json16.data()), (uint32)(json16len/2)))
	{
		wxLogError(_T("ParseJSON failed to consume"));
		return AtObj();
	}

	if (!JS_FinishJSONParse(cx, parser, JSVAL_NULL))
	{
		wxLogError(_T("ParseJSON failed to finish"));
		return AtObj();
	}

	AtObj obj;
	obj.p = ConvertNode(cx, vp);

	return obj;
}
// Convert from a jsval to an AtNode
static AtSmartPtr<AtNode> ConvertNode(JSContext* cx, jsval node)
{
	AtSmartPtr<AtNode> obj (new AtNode());

	// Non-objects get converted into strings
	if (!JSVAL_IS_OBJECT(node))
	{
		JSString* str = JS_ValueToString(cx, node);
		if (!str)
			return obj; // error
		size_t valueLen;
		const jschar* valueChars = JS_GetStringCharsAndLength(cx, str, &valueLen);
		if (!valueChars)
			return obj; // error
		wxString valueWx(reinterpret_cast<const char*>(valueChars), wxMBConvUTF16(), valueLen*2);

		obj->value = valueWx.c_str();

		// Annotate numbers/booleans specially, to allow round-tripping
		if (JSVAL_IS_NUMBER(node))
		{
			obj->children.insert(AtNode::child_pairtype(
				"@number", AtSmartPtr<AtNode>(new AtNode())
			));
		}
		else if (JSVAL_IS_BOOLEAN(node))
		{
			obj->children.insert(AtNode::child_pairtype(
				"@boolean", AtSmartPtr<AtNode>(new AtNode())
			));
		}

		return obj;
	}

	JSObject* it = JS_NewPropertyIterator(cx, JSVAL_TO_OBJECT(node));
	if (!it)
		return obj; // error

	while (true)
	{
		jsid idp;
		jsval val;
		if (! JS_NextProperty(cx, it, &idp) || ! JS_IdToValue(cx, idp, &val))
			return obj; // error
		if (val == JSVAL_VOID)
			break; // end of iteration
		if (! JSVAL_IS_STRING(val))
			continue; // ignore integer properties

		JSString* name = JSVAL_TO_STRING(val);
		size_t len;
		const jschar* chars = JS_GetStringCharsAndLength(cx, name, &len);
		wxString nameWx(reinterpret_cast<const char*>(chars), wxMBConvUTF16(), len*2);
		std::string nameStr(nameWx.ToUTF8().data());

		jsval vp;
		if (!JS_GetPropertyById(cx, JSVAL_TO_OBJECT(node), idp, &vp))
			return obj; // error

		// Unwrap arrays into a special format like <$name><item>$i0</item><item>...
		// (This assumes arrays aren't nested)
		if (JSVAL_IS_OBJECT(vp) && JS_IsArrayObject(cx, JSVAL_TO_OBJECT(vp)))
		{
			AtSmartPtr<AtNode> child(new AtNode());
			child->children.insert(AtNode::child_pairtype(
				"@array", AtSmartPtr<AtNode>(new AtNode())
			));

			jsuint arrayLength;
			if (!JS_GetArrayLength(cx, JSVAL_TO_OBJECT(vp), &arrayLength))
				return obj; // error

			for (jsuint i = 0; i < arrayLength; ++i)
			{
				jsval val;
				if (!JS_GetElement(cx, JSVAL_TO_OBJECT(vp), i, &val))
					return obj; // error

				child->children.insert(AtNode::child_pairtype(
					"item", ConvertNode(cx, val)
				));
			}

			obj->children.insert(AtNode::child_pairtype(
				nameStr, child
			));
		}
		else
		{
			obj->children.insert(AtNode::child_pairtype(
				nameStr, ConvertNode(cx, vp)
			));
		}
	}

	return obj;
}
Beispiel #3
0
MyTagLib::String OOPCharsetConv::utf16ToWide(const char *utf16, size_t numBytes) {
    wxWCharBuffer buf(wxMBConvUTF16().cMB2WC(utf16, numBytes, NULL));
    return buf ? (const wchar_t *) buf : MyTagLib::EmptyString;
}
Beispiel #4
0
char *OOPCharsetConv::wideToUtf16(const MyTagLib::String &wide) {
    return wxMBConvUTF16().cWC2MB(wide.c_str()).release();
}
Beispiel #5
0
 void RoundTripUTF16() { DoRoundTripTest(wxMBConvUTF16()); }