From e15c2864244149eb06b84dc6e4d83bd878a70f78 Mon Sep 17 00:00:00 2001 From: vng Date: Tue, 27 Aug 2013 16:29:33 +0300 Subject: [PATCH] Factor out JsonHandle as a smart pointer on json_t. --- 3party/jansson/jansson.pro | 2 + 3party/jansson/jansson_handle.cpp | 21 +++++++ 3party/jansson/jansson_handle.hpp | 71 ++++++++++++++++++++++++ 3party/jansson/myjansson.hpp | 66 ++++------------------ 3party/jansson/src/jansson.h | 3 +- map/map.pro | 1 - map_server/map_server.pro | 1 - platform/platform_tests/jansson_test.cpp | 4 +- platform/servers_list.cpp | 8 +-- platform/wifi_location_service.cpp | 4 +- storage/country.cpp | 45 ++++++++------- 11 files changed, 140 insertions(+), 86 deletions(-) create mode 100644 3party/jansson/jansson_handle.cpp create mode 100644 3party/jansson/jansson_handle.hpp diff --git a/3party/jansson/jansson.pro b/3party/jansson/jansson.pro index 87f2939ff0..ac4b0c23d8 100644 --- a/3party/jansson/jansson.pro +++ b/3party/jansson/jansson.pro @@ -16,6 +16,7 @@ SOURCES += \ src/memory.c \ src/error.c \ src/strconv.c \ + jansson_handle.cpp \ HEADERS += \ myjansson.hpp \ @@ -25,3 +26,4 @@ HEADERS += \ src/strbuffer.h \ src/utf.h \ src/jansson_config.h \ + jansson_handle.hpp \ diff --git a/3party/jansson/jansson_handle.cpp b/3party/jansson/jansson_handle.cpp new file mode 100644 index 0000000000..3c1c0dc021 --- /dev/null +++ b/3party/jansson/jansson_handle.cpp @@ -0,0 +1,21 @@ +#include "jansson_handle.hpp" + +#include + + +namespace my +{ + +void JsonHandle::IncRef() +{ + if (m_pJson) + json_incref(m_pJson); +} + +void JsonHandle::DecRef() +{ + if (m_pJson) + json_decref(m_pJson); +} + +} diff --git a/3party/jansson/jansson_handle.hpp b/3party/jansson/jansson_handle.hpp new file mode 100644 index 0000000000..1eb5efedbe --- /dev/null +++ b/3party/jansson/jansson_handle.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "../../std/algorithm.hpp" + + +struct json_struct_t; + +namespace my +{ + +class JsonHandle +{ + void IncRef(); + void DecRef(); + +public: + JsonHandle(json_struct_t * pJson = 0) : m_pJson(pJson) + { + IncRef(); + } + + JsonHandle(JsonHandle const & json) : m_pJson(json.m_pJson) + { + IncRef(); + } + + ~JsonHandle() + { + DecRef(); + } + + JsonHandle & operator = (JsonHandle const & json) + { + JsonHandle tmp(json); + tmp.swap(*this); + return *this; + } + + void swap(JsonHandle & json) + { + ::swap(m_pJson, json.m_pJson); + } + + json_struct_t * get() const + { + return m_pJson; + } + + json_struct_t * operator -> () const + { + return m_pJson; + } + + operator bool () const + { + return m_pJson != 0; + } + + /// Attach newly created object without incrementing ref count (it's already == 1). + void AttachNew(json_struct_t * pJson) + { + DecRef(); + + m_pJson = pJson; + } + +private: + json_struct_t * m_pJson; +}; + +} diff --git a/3party/jansson/myjansson.hpp b/3party/jansson/myjansson.hpp index 005052a33b..0f9c2b0ecc 100644 --- a/3party/jansson/myjansson.hpp +++ b/3party/jansson/myjansson.hpp @@ -1,75 +1,31 @@ -#include +#pragma once + +#include "jansson_handle.hpp" #include "../../base/exception.hpp" -#include "../../std/algorithm.hpp" + +#include + namespace my { class Json { + JsonHandle m_handle; + public: DECLARE_EXCEPTION(Exception, RootException); - explicit Json(json_t * pJson) : m_pJson(pJson) - { - } - explicit Json(char const * s) { json_error_t jsonError; - m_pJson = json_loads(s, 0, &jsonError); - if (!m_pJson) + m_handle.AttachNew(json_loads(s, 0, &jsonError)); + if (!m_handle) MYTHROW(Exception, (jsonError.line, jsonError.text)); } - ~Json() - { - if (m_pJson) - json_decref(m_pJson); - } - - Json(Json const & json) : m_pJson(json.m_pJson) - { - if (m_pJson) - json_incref(m_pJson); - } - - Json & operator = (Json const & json) - { - Json tmp(json); - tmp.swap(*this); - return *this; - } - - void swap(Json & json) - { - ::swap(m_pJson, json.m_pJson); - } - - json_t * get() const - { - return m_pJson; - } - - json_t * operator -> () const - { - return m_pJson; - } - - operator json_t * () const - { - return m_pJson; - } - - operator bool () const - { - return m_pJson != 0; - } - -private: - json_t * m_pJson; + json_t * get() const { return m_handle.get(); } }; } - diff --git a/3party/jansson/src/jansson.h b/3party/jansson/src/jansson.h index 352c6ce525..7ad6f0e778 100644 --- a/3party/jansson/src/jansson.h +++ b/3party/jansson/src/jansson.h @@ -47,7 +47,8 @@ typedef enum { JSON_NULL } json_type; -typedef struct { +typedef struct json_struct_t +{ json_type type; size_t refcount; } json_t; diff --git a/map/map.pro b/map/map.pro index c382fe20c4..026f156803 100644 --- a/map/map.pro +++ b/map/map.pro @@ -10,7 +10,6 @@ ROOT_DIR = .. INCLUDEPATH *= $$ROOT_DIR/3party/protobuf/src # use expat from the system on linux !linux*: INCLUDEPATH *= $$ROOT_DIR/3party/expat/lib -INCLUDEPATH *= $$ROOT_DIR/3party/jansson/src include($$ROOT_DIR/common.pri) diff --git a/map_server/map_server.pro b/map_server/map_server.pro index a214ed67bb..c6adbd75a3 100644 --- a/map_server/map_server.pro +++ b/map_server/map_server.pro @@ -16,7 +16,6 @@ INSTALLS += target QT += core gui opengl network -INCLUDEPATH *= $$ROOT_DIR/3party/jansson/src INCLUDEPATH *= $$ROOT_DIR/3party/qjsonrpc/src INCLUDEPATH *= $$ROOT_DIR/3party/gflags/src diff --git a/platform/platform_tests/jansson_test.cpp b/platform/platform_tests/jansson_test.cpp index a3f819cc02..efad4dc094 100644 --- a/platform/platform_tests/jansson_test.cpp +++ b/platform/platform_tests/jansson_test.cpp @@ -11,8 +11,8 @@ UNIT_TEST(Jansson_Smoke) "\"accuracy\":22.0},\"access_token\":\"2:vC65Xv0mxMtsNVf4:hY5YSIkuFfnAU77z\"}"; my::Json root(str); - TEST(json_is_object(root), ()); - json_t * location = json_object_get(root, "location"); + TEST(json_is_object(root.get()), ()); + json_t * location = json_object_get(root.get(), "location"); TEST(json_is_object(location), ()); json_t * lat = json_object_get(location, "latitude"); diff --git a/platform/servers_list.cpp b/platform/servers_list.cpp index f0e10bd12a..2448affac9 100644 --- a/platform/servers_list.cpp +++ b/platform/servers_list.cpp @@ -21,16 +21,16 @@ bool ParseServerList(string const & jsonStr, vector & outUrls) try { my::Json root(jsonStr.c_str()); - for (size_t i = 0; i < json_array_size(root); ++i) + for (size_t i = 0; i < json_array_size(root.get()); ++i) { - char const * url = json_string_value(json_array_get(root, i)); + char const * url = json_string_value(json_array_get(root.get(), i)); if (url) outUrls.push_back(url); } } - catch (std::exception const & e) + catch (my::Json::Exception const & ex) { - LOG(LERROR, ("Can't parse server list json", e.what(), jsonStr)); + LOG(LERROR, ("Can't parse server list json:", ex.Msg(), jsonStr)); } return !outUrls.empty(); } diff --git a/platform/wifi_location_service.cpp b/platform/wifi_location_service.cpp index 3fd394c5a8..1989eb9d7e 100644 --- a/platform/wifi_location_service.cpp +++ b/platform/wifi_location_service.cpp @@ -29,9 +29,9 @@ namespace location { bool success = false; my::Json root(response.Data().c_str()); - if (json_is_object(root)) + if (json_is_object(root.get())) { - json_t * location = json_object_get(root, "location"); + json_t * location = json_object_get(root.get(), "location"); if (json_is_object(location)) { json_t * lat = json_object_get(location, "latitude"); diff --git a/storage/country.cpp b/storage/country.cpp index 9182923576..f5297c1bc0 100644 --- a/storage/country.cpp +++ b/storage/country.cpp @@ -114,15 +114,15 @@ int64_t LoadCountriesImpl(string const & jsonBuffer, ToDo & toDo) try { my::Json root(jsonBuffer.c_str()); - version = json_integer_value(json_object_get(root, "v")); - json_t * children = json_object_get(root, "g"); + version = json_integer_value(json_object_get(root.get(), "v")); + json_t * children = json_object_get(root.get(), "g"); if (!children) MYTHROW(my::Json::Exception, ("Root country doesn't have any groups")); LoadGroupImpl(0, children, toDo); } - catch (my::Json::Exception const & e) + catch (my::Json::Exception const & ex) { - LOG(LERROR, (e.what())); + LOG(LERROR, (ex.Msg())); return -1; } @@ -231,16 +231,19 @@ void SaveImpl(T const & v, json_t * jParent) size_t const siblingsCount = v.SiblingsCount(); CHECK_GREATER(siblingsCount, 0, ()); - my::Json jArray(json_array()); + my::JsonHandle jArray; + jArray.AttachNew(json_array()); for (size_t i = 0; i < siblingsCount; ++i) { - my::Json jCountry(json_object()); + my::JsonHandle jCountry; + jCountry.AttachNew(json_object()); + string const strName = v[i].Value().Name(); CHECK(!strName.empty(), ("Empty country name?")); - json_object_set_new(jCountry, "n", json_string(strName.c_str())); + json_object_set_new(jCountry.get(), "n", json_string(strName.c_str())); string const strFlag = v[i].Value().Flag(); if (!strFlag.empty()) - json_object_set_new(jCountry, "c", json_string(strFlag.c_str())); + json_object_set_new(jCountry.get(), "c", json_string(strFlag.c_str())); size_t countriesCount = v[i].Value().GetFilesCount(); ASSERT_LESS_OR_EQUAL(countriesCount, 1, ()); @@ -249,30 +252,32 @@ void SaveImpl(T const & v, json_t * jParent) CountryFile const & file = v[i].Value().GetFile(); int64_t const price = file.m_price; CHECK_GREATER_OR_EQUAL(price, 0, ("Invalid price")); - json_object_set_new(jCountry, "p", json_integer(price)); + json_object_set_new(jCountry.get(), "p", json_integer(price)); string const strFile = file.m_fileName; if (strFile != strName) - json_object_set_new(jCountry, "f", json_string(strFile.c_str())); - json_object_set_new(jCountry, "s", json_integer(file.m_remoteSize)); + json_object_set_new(jCountry.get(), "f", json_string(strFile.c_str())); + json_object_set_new(jCountry.get(), "s", json_integer(file.m_remoteSize)); } if (v[i].SiblingsCount()) - SaveImpl(v[i], jCountry); + SaveImpl(v[i], jCountry.get()); - json_array_append(jArray, jCountry); + json_array_append(jArray.get(), jCountry.get()); } - json_object_set(jParent, "g", jArray); + json_object_set(jParent, "g", jArray.get()); } bool SaveCountries(int64_t version, CountriesContainerT const & countries, string & jsonBuffer) { - jsonBuffer.clear(); - my::Json root(json_object()); - json_object_set_new(root, "v", json_integer(version)); - json_object_set_new(root, "n", json_string("World")); - SaveImpl(countries, root); - char * res = json_dumps(root, JSON_PRESERVE_ORDER | JSON_COMPACT | JSON_INDENT(1)); + my::JsonHandle root; + root.AttachNew(json_object()); + + json_object_set_new(root.get(), "v", json_integer(version)); + json_object_set_new(root.get(), "n", json_string("World")); + SaveImpl(countries, root.get()); + + char * res = json_dumps(root.get(), JSON_PRESERVE_ORDER | JSON_COMPACT | JSON_INDENT(1)); jsonBuffer = res; free(res); return true;