diff options
-rw-r--r-- | DEPS | 13 | ||||
-rw-r--r-- | build/config/BUILD.gn | 19 | ||||
-rw-r--r-- | osp_base/BUILD.gn | 10 | ||||
-rw-r--r-- | osp_base/DEPS | 1 | ||||
-rw-r--r-- | osp_base/error.h | 3 | ||||
-rw-r--r-- | osp_base/json/json_reader.cc | 40 | ||||
-rw-r--r-- | osp_base/json/json_reader.h | 33 | ||||
-rw-r--r-- | osp_base/json/json_reader_unittest.cc | 53 | ||||
-rw-r--r-- | osp_base/json/json_writer.cc | 46 | ||||
-rw-r--r-- | osp_base/json/json_writer.h | 34 | ||||
-rw-r--r-- | osp_base/json/json_writer_unittest.cc | 32 | ||||
-rw-r--r-- | third_party/.gitignore | 1 | ||||
-rw-r--r-- | third_party/jsoncpp/BUILD.gn | 53 |
13 files changed, 334 insertions, 4 deletions
@@ -14,7 +14,7 @@ vars = { 'chromium_git': 'https://chromium.googlesource.com', # TODO(jophba): move to googlesource external for github repos. - 'github': "https://github.com", + 'github': 'https://github.com', # NOTE: Strangely enough, this will be overridden by any _parent_ DEPS, so # in Chromium it will correctly be True. @@ -34,11 +34,13 @@ deps = { '@' + '703984f9d1674c2cfc259904a5a7fba4990cca4b', 'condition': 'checkout_openscreen_cast_internal', }, + 'buildtools': { 'url': Var('chromium_git')+ '/chromium/src/buildtools' + '@' + 'd5c58b84d50d256968271db459cd29b22bff1ba2', 'condition': 'not build_with_chromium', }, + 'buildtools/linux64': { 'packages': [ { @@ -49,6 +51,7 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_linux', }, + 'buildtools/mac': { 'packages': [ { @@ -59,6 +62,14 @@ deps = { 'dep_type': 'cipd', 'condition': 'checkout_mac', }, + + 'third_party/jsoncpp/src': { + 'url': Var('chromium_git') + + '/external/github.com/open-source-parsers/jsoncpp.git' + + '@' + '5b91551f3944d69e0090d6b6528852207de78078', + 'condition': 'not build_with_chromium', + }, + 'third_party/googletest/src': { 'url': Var('chromium_git') + '/external/github.com/google/googletest.git' + diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn index e486be03..708a2b8d 100644 --- a/build/config/BUILD.gn +++ b/build/config/BUILD.gn @@ -33,8 +33,23 @@ config("compiler_defaults") { } config("no_exceptions") { - cflags_cc = [ "-fno-exceptions" ] - cflags_objcc = [ "-fno-exceptions" ] + # -fno-exceptions causes the compiler to choose the implementation of the STL + # that uses abort() calls instead of throws, as well as issue compile errors + # for throw calls in user ccode. The no*unwind-tables flags disable generation + # of static unwind tables that are typically used for exceptions, resulting + # in typically smaller object sizes. For some information, see: + # https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-funwind-tables-1203 + cflags_cc = [ + "-fno-exceptions", + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", + ] + + cflags_objcc = [ + "-fno-exceptions", + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", + ] } config("no_rtti") { diff --git a/osp_base/BUILD.gn b/osp_base/BUILD.gn index 737e921f..d8b1e3c5 100644 --- a/osp_base/BUILD.gn +++ b/osp_base/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. +# Copyright 2019 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -15,6 +15,10 @@ source_set("osp_base") { "export.h", "ip_address.cc", "ip_address.h", + "json/json_reader.cc", + "json/json_reader.h", + "json/json_writer.cc", + "json/json_writer.h", "location.cc", "location.h", "macros.h", @@ -28,6 +32,7 @@ source_set("osp_base") { deps = [ "../third_party/abseil", "../third_party/boringssl", + "../third_party/jsoncpp", ] configs += [ "../build:allow_build_from_embedder" ] @@ -40,6 +45,8 @@ source_set("osp_base_unittests") { "big_endian_unittest.cc", "error_unittest.cc", "ip_address_unittest.cc", + "json/json_reader_unittest.cc", + "json/json_writer_unittest.cc", "location_unittest.cc", "scoped_pipe_unittest.cc", ] @@ -49,6 +56,7 @@ source_set("osp_base_unittests") { "../third_party/abseil", "../third_party/googletest:gmock", "../third_party/googletest:gtest", + "../third_party/jsoncpp", ] configs += [ "../build:allow_build_from_embedder" ] diff --git a/osp_base/DEPS b/osp_base/DEPS index 96d75425..eaaf2fef 100644 --- a/osp_base/DEPS +++ b/osp_base/DEPS @@ -5,4 +5,5 @@ include_rules = [ '-platform', '+platform/api/logging.h', + '+json', ] diff --git a/osp_base/error.h b/osp_base/error.h index 5ad1792e..5c9ba2d5 100644 --- a/osp_base/error.h +++ b/osp_base/error.h @@ -73,6 +73,9 @@ class Error { kAlreadyClosed, kNoStartedPresentation, kPresentationAlreadyStarted, + + kJsonParseError, + kJsonWriteError, }; Error(); diff --git a/osp_base/json/json_reader.cc b/osp_base/json/json_reader.cc new file mode 100644 index 00000000..1750c2ad --- /dev/null +++ b/osp_base/json/json_reader.cc @@ -0,0 +1,40 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "osp_base/json/json_reader.h" + +#include <memory> +#include <string> + +#include "json/value.h" +#include "osp_base/error.h" +#include "platform/api/logging.h" + +namespace openscreen { +namespace { +// A reasonable maximum stack depth, may need to adjust as needs change. +constexpr int kMaxStackDepth = 64; +} // namespace + +JsonReader::JsonReader() { + builder_["stackLimit"] = kMaxStackDepth; +} + +ErrorOr<Json::Value> JsonReader::Read(absl::string_view document) { + if (document.empty()) { + return ErrorOr<Json::Value>(Error::Code::kJsonParseError, "empty document"); + } + + Json::Value root_node; + std::string error_msg; + std::unique_ptr<Json::CharReader> reader(builder_.newCharReader()); + const bool succeeded = + reader->parse(document.begin(), document.end(), &root_node, &error_msg); + if (!succeeded) { + return ErrorOr<Json::Value>(Error::Code::kJsonParseError, error_msg); + } + + return root_node; +} +} // namespace openscreen diff --git a/osp_base/json/json_reader.h b/osp_base/json/json_reader.h new file mode 100644 index 00000000..be4a5e06 --- /dev/null +++ b/osp_base/json/json_reader.h @@ -0,0 +1,33 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef OSP_BASE_JSON_JSON_READER_H_ +#define OSP_BASE_JSON_JSON_READER_H_ + +#include <memory> + +#include "absl/strings/string_view.h" +#include "json/reader.h" + +namespace Json { +class Value; +} + +namespace openscreen { +template <typename T> +class ErrorOr; + +class JsonReader { + public: + JsonReader(); + + ErrorOr<Json::Value> Read(absl::string_view document); + + private: + Json::CharReaderBuilder builder_; +}; + +} // namespace openscreen + +#endif // OSP_BASE_JSON_JSON_READER_H_
\ No newline at end of file diff --git a/osp_base/json/json_reader_unittest.cc b/osp_base/json/json_reader_unittest.cc new file mode 100644 index 00000000..21729ebf --- /dev/null +++ b/osp_base/json/json_reader_unittest.cc @@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "osp_base/json/json_reader.h" + +#include <string> + +#include "osp_base/error.h" +#include "third_party/googletest/src/googlemock/include/gmock/gmock.h" +#include "third_party/googletest/src/googletest/include/gtest/gtest.h" + +namespace openscreen { +namespace { +template <typename Value> +void AssertError(ErrorOr<Value> error_or, Error::Code code) { + EXPECT_EQ(error_or.error().code(), code); +} +} // namespace + +TEST(JsonReaderTest, MalformedDocumentReturnsParseError) { + JsonReader reader; + + const std::array<std::string, 4> kMalformedDocuments{ + {"", "{", "{ foo: bar }", R"({"foo": "bar", "foo": baz})"}}; + + for (auto& document : kMalformedDocuments) { + AssertError(reader.Read(document), Error::Code::kJsonParseError); + } +} + +TEST(JsonReaderTest, ValidEmptyDocumentParsedCorrectly) { + JsonReader reader; + + const auto actual = reader.Read("{}"); + + EXPECT_TRUE(actual.is_value()); + EXPECT_EQ(actual.value().getMemberNames().size(), 0); +} + +// Jsoncpp has its own suite of tests ensure that things are parsed correctly, +// so we only do some rudimentary checks here to make sure we didn't mangle +// the value. +TEST(JsonReaderTest, ValidDocumentParsedCorrectly) { + JsonReader reader; + + const auto actual = reader.Read(R"({"foo": "bar", "baz": 1337})"); + + EXPECT_TRUE(actual.is_value()); + EXPECT_EQ(actual.value().getMemberNames().size(), 2); +} + +} // namespace openscreen diff --git a/osp_base/json/json_writer.cc b/osp_base/json/json_writer.cc new file mode 100644 index 00000000..1d3d94f9 --- /dev/null +++ b/osp_base/json/json_writer.cc @@ -0,0 +1,46 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "osp_base/json/json_writer.h" + +#include <memory> +#include <sstream> +#include <string> +#include <utility> + +#include "json/value.h" +#include "osp_base/error.h" +#include "platform/api/logging.h" + +namespace openscreen { +JsonWriter::JsonWriter() { +#ifndef _DEBUG + // Default is to "pretty print" the output JSON in a human readable + // format. On non-debug builds, we can remove pretty printing by simply + // getting rid of all indentation. + factory_["indentation"] = ""; +#endif +} + +ErrorOr<std::string> JsonWriter::Write(const Json::Value& value) { + if (value.empty()) { + return ErrorOr<std::string>(Error::Code::kJsonWriteError, "Empty value"); + } + + std::unique_ptr<Json::StreamWriter> const writer(factory_.newStreamWriter()); + std::stringstream stream; + writer->write(value, &stream); + stream << std::endl; + + if (!stream) { + // Note: jsoncpp doesn't give us more information about what actually + // went wrong, just says to "check the stream". However, failures on + // the stream should be rare, as we do not throw any errors in the jsoncpp + // library. + return ErrorOr<std::string>(Error::Code::kJsonWriteError, "Invalid stream"); + } + + return stream.str(); +} +} // namespace openscreen diff --git a/osp_base/json/json_writer.h b/osp_base/json/json_writer.h new file mode 100644 index 00000000..bad9484a --- /dev/null +++ b/osp_base/json/json_writer.h @@ -0,0 +1,34 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef OSP_BASE_JSON_JSON_WRITER_H_ +#define OSP_BASE_JSON_JSON_WRITER_H_ + +#include <memory> +#include <string> + +#include "absl/strings/string_view.h" +#include "json/writer.h" + +namespace Json { +class Value; +} + +namespace openscreen { +template <typename T> +class ErrorOr; + +class JsonWriter { + public: + JsonWriter(); + + ErrorOr<std::string> Write(const Json::Value& value); + + private: + Json::StreamWriterBuilder factory_; +}; + +} // namespace openscreen + +#endif // OSP_BASE_JSON_JSON_WRITER_H_ diff --git a/osp_base/json/json_writer_unittest.cc b/osp_base/json/json_writer_unittest.cc new file mode 100644 index 00000000..6a4c00e1 --- /dev/null +++ b/osp_base/json/json_writer_unittest.cc @@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "osp_base/json/json_writer.h" + +#include "osp_base/error.h" +#include "third_party/googletest/src/googlemock/include/gmock/gmock.h" +#include "third_party/googletest/src/googletest/include/gtest/gtest.h" + +namespace openscreen { + +TEST(JsonWriterTest, NullValueReturnsError) { + JsonWriter writer; + + const auto null_value = Json::Value(); + const auto actual = writer.Write(null_value); + + EXPECT_TRUE(actual.is_error()); + EXPECT_EQ(actual.error().code(), Error::Code::kJsonWriteError); +} + +TEST(JsonWriterTest, ValidValueReturnsString) { + JsonWriter writer; + + const Json::Int64 value = 31337; + const auto actual = writer.Write(value); + + EXPECT_TRUE(actual.is_value()); + EXPECT_EQ(actual.value(), "31337\n"); +} +} // namespace openscreen diff --git a/third_party/.gitignore b/third_party/.gitignore index 78052e47..05b0106f 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore @@ -2,5 +2,6 @@ abseil/src/ boringssl/src/ chromium_quic/src/ googletest/src/ +jsoncpp/src/ mDNSResponder/src/ tinycbor/src/ diff --git a/third_party/jsoncpp/BUILD.gn b/third_party/jsoncpp/BUILD.gn new file mode 100644 index 00000000..a889495c --- /dev/null +++ b/third_party/jsoncpp/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build_overrides/build.gni") + +if (build_with_chromium) { + source_set("jsoncpp") { + public_deps = [ + "//third_party/jsoncpp", + ] + } +} else { + config("jsoncpp_config") { + include_dirs = [ "//third_party/jsoncpp/src/include" ] + cflags_cc = [ + "-Wno-exit-time-destructors", + "-Wno-implicit-fallthrough", + ] + } + + source_set("jsoncpp") { + sources = [ + "overrides.h", + "src/include/json/assertions.h", + "src/include/json/autolink.h", + "src/include/json/config.h", + "src/include/json/features.h", + "src/include/json/forwards.h", + "src/include/json/json.h", + "src/include/json/reader.h", + "src/include/json/value.h", + "src/include/json/writer.h", + "src/src/lib_json/json_batchallocator.h", + "src/src/lib_json/json_reader.cpp", + "src/src/lib_json/json_tool.h", + "src/src/lib_json/json_value.cpp", + "src/src/lib_json/json_writer.cpp", + ] + + include_dirs = [ "src/src/lib_json" ] + + defines = [ "JSON_USE_EXCEPTION=0" ] + + # Need exceptions on for throwRuntimeError. This will result in an abort + # once it crosses into parent code (which is compiled without exceptions). + # TODO(jophba): remove once jsoncpp patch fixing JSON_USE_EXCEPTION + # is upstreamed and DEPS rolled. + configs -= [ "//build/config:no_exceptions" ] + + public_configs = [ ":jsoncpp_config" ] + } +} |