Skip to content

Commit

Permalink
CJSONVariantWriter: use RapidJSON instead of yajl
Browse files Browse the repository at this point in the history
  • Loading branch information
Montellese committed Sep 10, 2015
1 parent 8b0085b commit 00f83a7
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 132 deletions.
5 changes: 4 additions & 1 deletion xbmc/interfaces/json-rpc/IJSONRPCAnnouncer.h
Expand Up @@ -44,7 +44,10 @@ namespace JSONRPC
root["params"]["data"] = data;
root["params"]["sender"] = sender;

return CJSONVariantWriter::Write(root, compactOutput);
std::string str;
CJSONVariantWriter::Write(root, str, compactOutput);

return str;
}
};
}
10 changes: 8 additions & 2 deletions xbmc/interfaces/json-rpc/JSONRPC.cpp
Expand Up @@ -274,7 +274,10 @@ std::string CJSONRPC::MethodCall(const std::string &inputString, ITransportLayer
hasResponse = true;
}

std::string str = hasResponse ? CJSONVariantWriter::Write(outputroot, g_advancedSettings.m_jsonOutputCompact) : "";
std::string str;
if (hasResponse)
CJSONVariantWriter::Write(outputroot, str, g_advancedSettings.m_jsonOutputCompact);

return str;
}

Expand All @@ -301,7 +304,10 @@ bool CJSONRPC::HandleMethodCall(const CVariant& request, CVariant& response, ITr
}
else
{
CLog::Log(LOGERROR, "JSONRPC: Failed to parse '%s'\n", CJSONVariantWriter::Write(request, true).c_str());
std::string str;
CJSONVariantWriter::Write(request, str, true);

CLog::Log(LOGERROR, "JSONRPC: Failed to parse '%s'\n", str.c_str());
errorCode = InvalidRequest;
}

Expand Down
4 changes: 3 additions & 1 deletion xbmc/interfaces/python/XBPython.cpp
Expand Up @@ -118,7 +118,9 @@ void XBPython::Announce(AnnouncementFlag flag, const char *sender, const char *m
OnDPMSActivated();
}

OnNotification(sender, std::string(ANNOUNCEMENT::AnnouncementFlagToString(flag)) + "." + std::string(message), CJSONVariantWriter::Write(data, g_advancedSettings.m_jsonOutputCompact));
std::string jsonData;
if (CJSONVariantWriter::Write(data, jsonData, g_advancedSettings.m_jsonOutputCompact))
OnNotification(sender, std::string(ANNOUNCEMENT::AnnouncementFlagToString(flag)) + "." + std::string(message), jsonData);
}

// message all registered callbacks that we started playing
Expand Down
8 changes: 7 additions & 1 deletion xbmc/network/httprequesthandler/HTTPJsonRpcHandler.cpp
Expand Up @@ -91,7 +91,13 @@ int CHTTPJsonRpcHandler::HandleRequest()
// get the whole output of JSONRPC.Introspect
CVariant result;
JSONRPC::CJSONServiceDescription::Print(result, m_request.webserver, &client);
m_responseData = CJSONVariantWriter::Write(result, false);
if (!CJSONVariantWriter::Write(result, m_responseData, false))
{
m_response.type = HTTPError;
m_response.status = MHD_HTTP_INTERNAL_SERVER_ERROR;

return MHD_YES;
}
}
else
{
Expand Down
3 changes: 1 addition & 2 deletions xbmc/playlists/SmartPlayList.cpp
Expand Up @@ -1290,8 +1290,7 @@ bool CSmartPlaylist::SaveAsJson(std::string &json, bool full /* = true */) const
if (!Save(xsp, full))
return false;

json = CJSONVariantWriter::Write(xsp, true);
return json.size() > 0;
return CJSONVariantWriter::Write(xsp, json, true) && !json.empty();
}

void CSmartPlaylist::Reset()
Expand Down
174 changes: 74 additions & 100 deletions xbmc/utils/JSONVariantWriter.cpp
@@ -1,130 +1,104 @@
/*
* Copyright (C) 2005-2013 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include <locale>
* Copyright (C) 2015 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include "JSONVariantWriter.h"
#include "utils/Variant.h"

std::string CJSONVariantWriter::Write(const CVariant &value, bool compact)
{
std::string output;

yajl_gen g = yajl_gen_alloc(NULL);
yajl_gen_config(g, yajl_gen_beautify, compact ? 0 : 1);
yajl_gen_config(g, yajl_gen_indent_string, "\t");
#include <rapidjson/prettywriter.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>

// Set locale to classic ("C") to ensure valid JSON numbers
#ifndef TARGET_WINDOWS
const char *currentLocale = setlocale(LC_NUMERIC, NULL);
std::string backupLocale;
if (currentLocale != NULL && (currentLocale[0] != 'C' || currentLocale[1] != 0))
{
backupLocale = currentLocale;
setlocale(LC_NUMERIC, "C");
}
#else // TARGET_WINDOWS
const wchar_t* const currentLocale = _wsetlocale(LC_NUMERIC, NULL);
std::wstring backupLocale;
if (currentLocale != NULL && (currentLocale[0] != L'C' || currentLocale[1] != 0))
{
backupLocale = currentLocale;
_wsetlocale(LC_NUMERIC, L"C");
}
#endif // TARGET_WINDOWS

if (InternalWrite(g, value))
{
const unsigned char * buffer;

size_t length;
yajl_gen_get_buf(g, &buffer, &length);
output = std::string((const char *)buffer, length);
}

// Re-set locale to what it was before using yajl
#ifndef TARGET_WINDOWS
if (!backupLocale.empty())
setlocale(LC_NUMERIC, backupLocale.c_str());
#else // TARGET_WINDOWS
if (!backupLocale.empty())
_wsetlocale(LC_NUMERIC, backupLocale.c_str());
#endif // TARGET_WINDOWS

yajl_gen_clear(g);
yajl_gen_free(g);

return output;
}
#include "utils/Variant.h"

bool CJSONVariantWriter::InternalWrite(yajl_gen g, const CVariant &value)
template<class TWriter>
bool InternalWrite(TWriter& writer, const CVariant &value)
{
bool success = false;

switch (value.type())
{
case CVariant::VariantTypeInteger:
success = yajl_gen_status_ok == yajl_gen_integer(g, (long long int)value.asInteger());
break;
return writer.Int64(value.asInteger());

case CVariant::VariantTypeUnsignedInteger:
success = yajl_gen_status_ok == yajl_gen_integer(g, (long long int)value.asUnsignedInteger());
break;
return writer.Uint64(value.asUnsignedInteger());

case CVariant::VariantTypeDouble:
success = yajl_gen_status_ok == yajl_gen_double(g, value.asDouble());
break;
return writer.Double(value.asDouble());

case CVariant::VariantTypeBoolean:
success = yajl_gen_status_ok == yajl_gen_bool(g, value.asBoolean() ? 1 : 0);
break;
return writer.Bool(value.asBoolean());

case CVariant::VariantTypeString:
success = yajl_gen_status_ok == yajl_gen_string(g, (const unsigned char*)value.c_str(), (size_t)value.size());
break;
return writer.String(value.c_str(), value.size());

case CVariant::VariantTypeArray:
success = yajl_gen_status_ok == yajl_gen_array_open(g);
if (!writer.StartArray())
return false;

for (CVariant::const_iterator_array itr = value.begin_array(); itr != value.end_array() && success; ++itr)
success &= InternalWrite(g, *itr);
for (CVariant::const_iterator_array itr = value.begin_array(); itr != value.end_array(); ++itr)
{
if (!InternalWrite(writer, *itr))
return false;
}

if (success)
success = yajl_gen_status_ok == yajl_gen_array_close(g);
return writer.EndArray(value.size());

break;
case CVariant::VariantTypeObject:
success = yajl_gen_status_ok == yajl_gen_map_open(g);
if (!writer.StartObject())
return false;

for (CVariant::const_iterator_map itr = value.begin_map(); itr != value.end_map() && success; ++itr)
for (CVariant::const_iterator_map itr = value.begin_map(); itr != value.end_map(); ++itr)
{
success &= yajl_gen_status_ok == yajl_gen_string(g, (const unsigned char*)itr->first.c_str(), (size_t)itr->first.length());
if (success)
success &= InternalWrite(g, itr->second);
if (!writer.Key(itr->first.c_str()) ||
!InternalWrite(writer, itr->second))
return false;
}

if (success)
success &= yajl_gen_status_ok == yajl_gen_map_close(g);
return writer.EndObject(value.size());

break;
case CVariant::VariantTypeConstNull:
case CVariant::VariantTypeNull:
default:
success = yajl_gen_status_ok == yajl_gen_null(g);
break;
return writer.Null();
}

return false;
}

bool CJSONVariantWriter::Write(const CVariant &value, std::string& output, bool compact)
{
rapidjson::StringBuffer stringBuffer;
if (compact)
{
rapidjson::Writer<rapidjson::StringBuffer> writer(stringBuffer);

if (!InternalWrite(writer, value) || !writer.IsComplete())
return false;
}
else
{
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(stringBuffer);
writer.SetIndent('\t', 1);

if (!InternalWrite(writer, value) || !writer.IsComplete())
return false;
}

return success;
output = stringBuffer.GetString();
return true;
}
43 changes: 21 additions & 22 deletions xbmc/utils/JSONVariantWriter.h
@@ -1,33 +1,32 @@
#pragma once
/*
* Copyright (C) 2005-2013 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
* Copyright (C) 2015 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include <yajl/yajl_gen.h>
#include <string>

class CVariant;

class CJSONVariantWriter
{
public:
static std::string Write(const CVariant &value, bool compact);
private:
static bool InternalWrite(yajl_gen g, const CVariant &value);
CJSONVariantWriter() = delete;

static bool Write(const CVariant &value, std::string& output, bool compact);
};

0 comments on commit 00f83a7

Please sign in to comment.