aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/BUILD.gn67
-rw-r--r--util/base64.cc16
-rw-r--r--util/base64.h3
-rw-r--r--util/base64_unittest.cc20
-rw-r--r--util/json/json_helpers.h93
-rw-r--r--util/json/json_helpers_unittest.cc121
-rw-r--r--util/simple_fraction.cc31
-rw-r--r--util/simple_fraction.h54
-rw-r--r--util/stringprintf.cc6
-rw-r--r--util/stringprintf.h10
-rw-r--r--util/stringprintf_unittest.cc4
11 files changed, 202 insertions, 223 deletions
diff --git a/util/BUILD.gn b/util/BUILD.gn
index 3f97e09e..90a7fe39 100644
--- a/util/BUILD.gn
+++ b/util/BUILD.gn
@@ -17,31 +17,14 @@ config("trace_logging_config") {
}
}
-source_set("util") {
+# The set of util classes which have no dependency on platform:api.
+source_set("base") {
sources = [
- "alarm.cc",
- "alarm.h",
"base64.cc",
"base64.h",
"big_endian.cc",
"big_endian.h",
"chrono_helpers.h",
- "crypto/certificate_utils.cc",
- "crypto/certificate_utils.h",
- "crypto/digest_sign.cc",
- "crypto/digest_sign.h",
- "crypto/openssl_util.cc",
- "crypto/openssl_util.h",
- "crypto/pem_helpers.cc",
- "crypto/pem_helpers.h",
- "crypto/random_bytes.cc",
- "crypto/random_bytes.h",
- "crypto/rsa_private_key.cc",
- "crypto/rsa_private_key.h",
- "crypto/secure_hash.cc",
- "crypto/secure_hash.h",
- "crypto/sha2.cc",
- "crypto/sha2.h",
"enum_name_table.h",
"flat_map.h",
"hashing.h",
@@ -59,10 +42,6 @@ source_set("util") {
"std_util.h",
"stringprintf.cc",
"stringprintf.h",
- "trace_logging.h",
- "trace_logging/macro_support.h",
- "trace_logging/scoped_trace_operations.cc",
- "trace_logging/scoped_trace_operations.h",
"url.cc",
"url.h",
"weak_ptr.h",
@@ -71,14 +50,13 @@ source_set("util") {
]
public_deps = [
- "../platform:api",
"../platform:base",
+ "../platform:logging",
"../third_party/abseil",
"../third_party/jsoncpp",
]
deps = [
- "../third_party/boringssl",
"../third_party/mozilla",
# We do a clone of Chrome's modp_b64 in order to share their BUILD.gn
@@ -86,6 +64,45 @@ source_set("util") {
"//third_party/modp_b64",
]
+ public_configs = [ "../build:openscreen_include_dirs" ]
+}
+
+source_set("util") {
+ sources = [
+ "alarm.cc",
+ "alarm.h",
+ "crypto/certificate_utils.cc",
+ "crypto/certificate_utils.h",
+ "crypto/digest_sign.cc",
+ "crypto/digest_sign.h",
+ "crypto/openssl_util.cc",
+ "crypto/openssl_util.h",
+ "crypto/pem_helpers.cc",
+ "crypto/pem_helpers.h",
+ "crypto/random_bytes.cc",
+ "crypto/random_bytes.h",
+ "crypto/rsa_private_key.cc",
+ "crypto/rsa_private_key.h",
+ "crypto/secure_hash.cc",
+ "crypto/secure_hash.h",
+ "crypto/sha2.cc",
+ "crypto/sha2.h",
+ "trace_logging.h",
+ "trace_logging/macro_support.h",
+ "trace_logging/scoped_trace_operations.cc",
+ "trace_logging/scoped_trace_operations.h",
+ ]
+
+ public_deps = [
+ ":base",
+ "../platform:api",
+ "../platform:base",
+ "../third_party/abseil",
+ "../third_party/jsoncpp",
+ ]
+
+ deps = [ "../third_party/boringssl" ]
+
public_configs = [
"../build:openscreen_include_dirs",
":trace_logging_config",
diff --git a/util/base64.cc b/util/base64.cc
index 06e120e0..64e34175 100644
--- a/util/base64.cc
+++ b/util/base64.cc
@@ -6,6 +6,10 @@
#include <stddef.h>
+#include <string>
+#include <utility>
+#include <vector>
+
#include "third_party/modp_b64/modp_b64.h"
#include "util/osp_logging.h"
#include "util/std_util.h"
@@ -33,20 +37,18 @@ std::string Encode(absl::string_view input) {
return out;
}
-bool Decode(absl::string_view input, std::string* output) {
- std::string out;
- out.resize(modp_b64_decode_len(input.size()));
+bool Decode(absl::string_view input, std::vector<uint8_t>* output) {
+ std::vector<uint8_t> out(modp_b64_decode_len(input.size()));
- // We don't null terminate the result since it is binary data.
- const size_t output_size =
- modp_b64_decode(data(out), input.data(), input.size());
+ const size_t output_size = modp_b64_decode(
+ reinterpret_cast<char*>(out.data()), input.data(), input.size());
if (output_size == MODP_B64_ERROR) {
return false;
}
// The output size from decode_len is generally larger than needed.
out.resize(output_size);
- output->swap(out);
+ *output = std::move(out);
return true;
}
diff --git a/util/base64.h b/util/base64.h
index b24c3b3f..a7af9eca 100644
--- a/util/base64.h
+++ b/util/base64.h
@@ -6,6 +6,7 @@
#define UTIL_BASE64_H_
#include <string>
+#include <vector>
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
@@ -23,7 +24,7 @@ std::string Encode(absl::string_view input);
// Decodes the base64 input string. Returns true if successful and false
// otherwise. The output string is only modified if successful. The decoding can
// be done in-place.
-bool Decode(absl::string_view input, std::string* output);
+bool Decode(absl::string_view input, std::vector<uint8_t>* output);
} // namespace base64
} // namespace openscreen
diff --git a/util/base64_unittest.cc b/util/base64_unittest.cc
index 28d4fb1d..873b5656 100644
--- a/util/base64_unittest.cc
+++ b/util/base64_unittest.cc
@@ -4,6 +4,9 @@
#include "util/base64.h"
+#include <string>
+#include <vector>
+
#include "gtest/gtest.h"
namespace openscreen {
@@ -14,13 +17,21 @@ namespace {
constexpr char kText[] = "hello world";
constexpr char kBase64Text[] = "aGVsbG8gd29ybGQ=";
+// More sophisticated comparisons here, such as EXPECT_STREQ, may
+// cause memory failures on some platforms (e.g. ASAN) due to mismatched
+// lengths.
+void CheckEquals(const char* expected, const std::vector<uint8_t>& actual) {
+ EXPECT_EQ(0, std::memcmp(actual.data(), expected, actual.size()));
+}
+
void CheckEncodeDecode(const char* to_encode, const char* encode_expected) {
std::string encoded = Encode(to_encode);
EXPECT_EQ(encode_expected, encoded);
- std::string decoded;
+ std::vector<uint8_t> decoded;
EXPECT_TRUE(Decode(encoded, &decoded));
- EXPECT_EQ(to_encode, decoded);
+
+ CheckEquals(to_encode, decoded);
}
} // namespace
@@ -52,8 +63,9 @@ TEST(Base64Test, InPlace) {
text = Encode(text);
EXPECT_EQ(kBase64Text, text);
- EXPECT_TRUE(Decode(text, &text));
- EXPECT_EQ(text, kText);
+ std::vector<uint8_t> out;
+ EXPECT_TRUE(Decode(text, &out));
+ CheckEquals(kText, out);
}
} // namespace base64
diff --git a/util/json/json_helpers.h b/util/json/json_helpers.h
index 1943973d..ebd25add 100644
--- a/util/json/json_helpers.h
+++ b/util/json/json_helpers.h
@@ -16,6 +16,7 @@
#include "json/value.h"
#include "platform/base/error.h"
#include "util/chrono_helpers.h"
+#include "util/json/json_serialization.h"
#include "util/simple_fraction.h"
// This file contains helper methods for parsing JSON, in an attempt to
@@ -23,53 +24,7 @@
namespace openscreen {
namespace json {
-// TODO(jophba): remove these methods after refactoring offer messaging.
-inline Error CreateParseError(const std::string& type) {
- return Error(Error::Code::kJsonParseError, "Failed to parse " + type);
-}
-
-inline Error CreateParameterError(const std::string& type) {
- return Error(Error::Code::kParameterInvalid, "Invalid parameter: " + type);
-}
-
-inline ErrorOr<bool> ParseBool(const Json::Value& parent,
- const std::string& field) {
- const Json::Value& value = parent[field];
- if (!value.isBool()) {
- return CreateParseError("bool field " + field);
- }
- return value.asBool();
-}
-
-inline ErrorOr<int> ParseInt(const Json::Value& parent,
- const std::string& field) {
- const Json::Value& value = parent[field];
- if (!value.isInt()) {
- return CreateParseError("integer field: " + field);
- }
- return value.asInt();
-}
-
-inline ErrorOr<uint32_t> ParseUint(const Json::Value& parent,
- const std::string& field) {
- const Json::Value& value = parent[field];
- if (!value.isUInt()) {
- return CreateParseError("unsigned integer field: " + field);
- }
- return value.asUInt();
-}
-
-inline ErrorOr<std::string> ParseString(const Json::Value& parent,
- const std::string& field) {
- const Json::Value& value = parent[field];
- if (!value.isString()) {
- return CreateParseError("string field: " + field);
- }
- return value.asString();
-}
-
-// TODO(jophba): offer messaging should use these methods instead.
-inline bool ParseBool(const Json::Value& value, bool* out) {
+inline bool TryParseBool(const Json::Value& value, bool* out) {
if (!value.isBool()) {
return false;
}
@@ -80,9 +35,9 @@ inline bool ParseBool(const Json::Value& value, bool* out) {
// A general note about parsing primitives. "Validation" in this context
// generally means ensuring that the values are non-negative, excepting doubles
// which may be negative in some cases.
-inline bool ParseAndValidateDouble(const Json::Value& value,
- double* out,
- bool allow_negative = false) {
+inline bool TryParseDouble(const Json::Value& value,
+ double* out,
+ bool allow_negative = false) {
if (!value.isDouble()) {
return false;
}
@@ -97,7 +52,7 @@ inline bool ParseAndValidateDouble(const Json::Value& value,
return true;
}
-inline bool ParseAndValidateInt(const Json::Value& value, int* out) {
+inline bool TryParseInt(const Json::Value& value, int* out) {
if (!value.isInt()) {
return false;
}
@@ -109,7 +64,7 @@ inline bool ParseAndValidateInt(const Json::Value& value, int* out) {
return true;
}
-inline bool ParseAndValidateUint(const Json::Value& value, uint32_t* out) {
+inline bool TryParseUint(const Json::Value& value, uint32_t* out) {
if (!value.isUInt()) {
return false;
}
@@ -117,7 +72,7 @@ inline bool ParseAndValidateUint(const Json::Value& value, uint32_t* out) {
return true;
}
-inline bool ParseAndValidateString(const Json::Value& value, std::string* out) {
+inline bool TryParseString(const Json::Value& value, std::string* out) {
if (!value.isString()) {
return false;
}
@@ -128,8 +83,8 @@ inline bool ParseAndValidateString(const Json::Value& value, std::string* out) {
// We want to be more robust when we parse fractions then just
// allowing strings, this will parse numeral values such as
// value: 50 as well as value: "50" and value: "100/2".
-inline bool ParseAndValidateSimpleFraction(const Json::Value& value,
- SimpleFraction* out) {
+inline bool TryParseSimpleFraction(const Json::Value& value,
+ SimpleFraction* out) {
if (value.isInt()) {
int parsed = value.asInt();
if (parsed < 0) {
@@ -155,10 +110,9 @@ inline bool ParseAndValidateSimpleFraction(const Json::Value& value,
return false;
}
-inline bool ParseAndValidateMilliseconds(const Json::Value& value,
- milliseconds* out) {
+inline bool TryParseMilliseconds(const Json::Value& value, milliseconds* out) {
int out_ms;
- if (!ParseAndValidateInt(value, &out_ms) || out_ms < 0) {
+ if (!TryParseInt(value, &out_ms) || out_ms < 0) {
return false;
}
*out = milliseconds(out_ms);
@@ -171,9 +125,9 @@ using Parser = std::function<bool(const Json::Value&, T*)>;
// NOTE: array parsing methods reset the output vector to an empty vector in
// any error case. This is especially useful for optional arrays.
template <typename T>
-bool ParseAndValidateArray(const Json::Value& value,
- Parser<T> parser,
- std::vector<T>* out) {
+bool TryParseArray(const Json::Value& value,
+ Parser<T> parser,
+ std::vector<T>* out) {
out->clear();
if (!value.isArray() || value.empty()) {
return false;
@@ -192,19 +146,18 @@ bool ParseAndValidateArray(const Json::Value& value,
return true;
}
-inline bool ParseAndValidateIntArray(const Json::Value& value,
- std::vector<int>* out) {
- return ParseAndValidateArray<int>(value, ParseAndValidateInt, out);
+inline bool TryParseIntArray(const Json::Value& value, std::vector<int>* out) {
+ return TryParseArray<int>(value, TryParseInt, out);
}
-inline bool ParseAndValidateUintArray(const Json::Value& value,
- std::vector<uint32_t>* out) {
- return ParseAndValidateArray<uint32_t>(value, ParseAndValidateUint, out);
+inline bool TryParseUintArray(const Json::Value& value,
+ std::vector<uint32_t>* out) {
+ return TryParseArray<uint32_t>(value, TryParseUint, out);
}
-inline bool ParseAndValidateStringArray(const Json::Value& value,
- std::vector<std::string>* out) {
- return ParseAndValidateArray<std::string>(value, ParseAndValidateString, out);
+inline bool TryParseStringArray(const Json::Value& value,
+ std::vector<std::string>* out) {
+ return TryParseArray<std::string>(value, TryParseString, out);
}
} // namespace json
diff --git a/util/json/json_helpers_unittest.cc b/util/json/json_helpers_unittest.cc
index c461cf93..eb05d3f6 100644
--- a/util/json/json_helpers_unittest.cc
+++ b/util/json/json_helpers_unittest.cc
@@ -26,9 +26,9 @@ struct Dummy {
}
};
-bool ParseAndValidateDummy(const Json::Value& value, Dummy* out) {
+bool TryParseDummy(const Json::Value& value, Dummy* out) {
int value_out;
- if (!ParseAndValidateInt(value, &value_out)) {
+ if (!TryParseInt(value, &value_out)) {
return false;
}
*out = Dummy{value_out};
@@ -37,7 +37,7 @@ bool ParseAndValidateDummy(const Json::Value& value, Dummy* out) {
} // namespace
-TEST(ParsingHelpersTest, ParseAndValidateDouble) {
+TEST(ParsingHelpersTest, TryParseDouble) {
const Json::Value kValid = 13.37;
const Json::Value kNotDouble = "coffee beans";
const Json::Value kNegativeDouble = -4.2;
@@ -45,62 +45,62 @@ TEST(ParsingHelpersTest, ParseAndValidateDouble) {
const Json::Value kNanDouble = std::nan("");
double out;
- EXPECT_TRUE(ParseAndValidateDouble(kValid, &out));
+ EXPECT_TRUE(TryParseDouble(kValid, &out));
EXPECT_DOUBLE_EQ(13.37, out);
- EXPECT_TRUE(ParseAndValidateDouble(kZeroDouble, &out));
+ EXPECT_TRUE(TryParseDouble(kZeroDouble, &out));
EXPECT_DOUBLE_EQ(0.0, out);
- EXPECT_FALSE(ParseAndValidateDouble(kNotDouble, &out));
- EXPECT_FALSE(ParseAndValidateDouble(kNegativeDouble, &out));
- EXPECT_FALSE(ParseAndValidateDouble(kNone, &out));
- EXPECT_FALSE(ParseAndValidateDouble(kNanDouble, &out));
+ EXPECT_FALSE(TryParseDouble(kNotDouble, &out));
+ EXPECT_FALSE(TryParseDouble(kNegativeDouble, &out));
+ EXPECT_FALSE(TryParseDouble(kNone, &out));
+ EXPECT_FALSE(TryParseDouble(kNanDouble, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateInt) {
+TEST(ParsingHelpersTest, TryParseInt) {
const Json::Value kValid = 1337;
const Json::Value kNotInt = "cold brew";
const Json::Value kNegativeInt = -42;
const Json::Value kZeroInt = 0;
int out;
- EXPECT_TRUE(ParseAndValidateInt(kValid, &out));
+ EXPECT_TRUE(TryParseInt(kValid, &out));
EXPECT_EQ(1337, out);
- EXPECT_TRUE(ParseAndValidateInt(kZeroInt, &out));
+ EXPECT_TRUE(TryParseInt(kZeroInt, &out));
EXPECT_EQ(0, out);
- EXPECT_FALSE(ParseAndValidateInt(kNone, &out));
- EXPECT_FALSE(ParseAndValidateInt(kNotInt, &out));
- EXPECT_FALSE(ParseAndValidateInt(kNegativeInt, &out));
+ EXPECT_FALSE(TryParseInt(kNone, &out));
+ EXPECT_FALSE(TryParseInt(kNotInt, &out));
+ EXPECT_FALSE(TryParseInt(kNegativeInt, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateUint) {
+TEST(ParsingHelpersTest, TryParseUint) {
const Json::Value kValid = 1337u;
const Json::Value kNotUint = "espresso";
const Json::Value kZeroUint = 0u;
uint32_t out;
- EXPECT_TRUE(ParseAndValidateUint(kValid, &out));
+ EXPECT_TRUE(TryParseUint(kValid, &out));
EXPECT_EQ(1337u, out);
- EXPECT_TRUE(ParseAndValidateUint(kZeroUint, &out));
+ EXPECT_TRUE(TryParseUint(kZeroUint, &out));
EXPECT_EQ(0u, out);
- EXPECT_FALSE(ParseAndValidateUint(kNone, &out));
- EXPECT_FALSE(ParseAndValidateUint(kNotUint, &out));
+ EXPECT_FALSE(TryParseUint(kNone, &out));
+ EXPECT_FALSE(TryParseUint(kNotUint, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateString) {
+TEST(ParsingHelpersTest, TryParseString) {
const Json::Value kValid = "macchiato";
const Json::Value kNotString = 42;
std::string out;
- EXPECT_TRUE(ParseAndValidateString(kValid, &out));
+ EXPECT_TRUE(TryParseString(kValid, &out));
EXPECT_EQ("macchiato", out);
- EXPECT_TRUE(ParseAndValidateString(kEmptyString, &out));
+ EXPECT_TRUE(TryParseString(kEmptyString, &out));
EXPECT_EQ("", out);
- EXPECT_FALSE(ParseAndValidateString(kNone, &out));
- EXPECT_FALSE(ParseAndValidateString(kNotString, &out));
+ EXPECT_FALSE(TryParseString(kNone, &out));
+ EXPECT_FALSE(TryParseString(kNotString, &out));
}
// Simple fraction validity is tested extensively in its unit tests, so we
// just check the major cases here.
-TEST(ParsingHelpersTest, ParseAndValidateSimpleFraction) {
+TEST(ParsingHelpersTest, TryParseSimpleFraction) {
const Json::Value kValid = "42/30";
const Json::Value kValidNumber = "42";
const Json::Value kUndefined = "5/0";
@@ -111,22 +111,22 @@ TEST(ParsingHelpersTest, ParseAndValidateSimpleFraction) {
const Json::Value kNegativeInteger = -5000;
SimpleFraction out;
- EXPECT_TRUE(ParseAndValidateSimpleFraction(kValid, &out));
+ EXPECT_TRUE(TryParseSimpleFraction(kValid, &out));
EXPECT_EQ((SimpleFraction{42, 30}), out);
- EXPECT_TRUE(ParseAndValidateSimpleFraction(kValidNumber, &out));
+ EXPECT_TRUE(TryParseSimpleFraction(kValidNumber, &out));
EXPECT_EQ((SimpleFraction{42, 1}), out);
- EXPECT_TRUE(ParseAndValidateSimpleFraction(kInteger, &out));
+ EXPECT_TRUE(TryParseSimpleFraction(kInteger, &out));
EXPECT_EQ((SimpleFraction{123, 1}), out);
- EXPECT_FALSE(ParseAndValidateSimpleFraction(kUndefined, &out));
- EXPECT_FALSE(ParseAndValidateSimpleFraction(kNegative, &out));
- EXPECT_FALSE(ParseAndValidateSimpleFraction(kInvalidNumber, &out));
- EXPECT_FALSE(ParseAndValidateSimpleFraction(kNotSimpleFraction, &out));
- EXPECT_FALSE(ParseAndValidateSimpleFraction(kNone, &out));
- EXPECT_FALSE(ParseAndValidateSimpleFraction(kEmptyString, &out));
- EXPECT_FALSE(ParseAndValidateSimpleFraction(kNegativeInteger, &out));
+ EXPECT_FALSE(TryParseSimpleFraction(kUndefined, &out));
+ EXPECT_FALSE(TryParseSimpleFraction(kNegative, &out));
+ EXPECT_FALSE(TryParseSimpleFraction(kInvalidNumber, &out));
+ EXPECT_FALSE(TryParseSimpleFraction(kNotSimpleFraction, &out));
+ EXPECT_FALSE(TryParseSimpleFraction(kNone, &out));
+ EXPECT_FALSE(TryParseSimpleFraction(kEmptyString, &out));
+ EXPECT_FALSE(TryParseSimpleFraction(kNegativeInteger, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateMilliseconds) {
+TEST(ParsingHelpersTest, TryParseMilliseconds) {
const Json::Value kValid = 1000;
const Json::Value kValidFloat = 500.0;
const Json::Value kNegativeNumber = -120;
@@ -134,18 +134,18 @@ TEST(ParsingHelpersTest, ParseAndValidateMilliseconds) {
const Json::Value kNotNumber = "affogato";
milliseconds out;
- EXPECT_TRUE(ParseAndValidateMilliseconds(kValid, &out));
+ EXPECT_TRUE(TryParseMilliseconds(kValid, &out));
EXPECT_EQ(milliseconds(1000), out);
- EXPECT_TRUE(ParseAndValidateMilliseconds(kValidFloat, &out));
+ EXPECT_TRUE(TryParseMilliseconds(kValidFloat, &out));
EXPECT_EQ(milliseconds(500), out);
- EXPECT_TRUE(ParseAndValidateMilliseconds(kZeroNumber, &out));
+ EXPECT_TRUE(TryParseMilliseconds(kZeroNumber, &out));
EXPECT_EQ(milliseconds(0), out);
- EXPECT_FALSE(ParseAndValidateMilliseconds(kNone, &out));
- EXPECT_FALSE(ParseAndValidateMilliseconds(kNegativeNumber, &out));
- EXPECT_FALSE(ParseAndValidateMilliseconds(kNotNumber, &out));
+ EXPECT_FALSE(TryParseMilliseconds(kNone, &out));
+ EXPECT_FALSE(TryParseMilliseconds(kNegativeNumber, &out));
+ EXPECT_FALSE(TryParseMilliseconds(kNotNumber, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateArray) {
+TEST(ParsingHelpersTest, TryParseArray) {
Json::Value valid_dummy_array;
valid_dummy_array[0] = 123;
valid_dummy_array[1] = 456;
@@ -155,16 +155,13 @@ TEST(ParsingHelpersTest, ParseAndValidateArray) {
invalid_dummy_array[1] = 456;
std::vector<Dummy> out;
- EXPECT_TRUE(ParseAndValidateArray<Dummy>(valid_dummy_array,
- ParseAndValidateDummy, &out));
+ EXPECT_TRUE(TryParseArray<Dummy>(valid_dummy_array, TryParseDummy, &out));
EXPECT_THAT(out, ElementsAre(Dummy{123}, Dummy{456}));
- EXPECT_FALSE(ParseAndValidateArray<Dummy>(invalid_dummy_array,
- ParseAndValidateDummy, &out));
- EXPECT_FALSE(
- ParseAndValidateArray<Dummy>(kEmptyArray, ParseAndValidateDummy, &out));
+ EXPECT_FALSE(TryParseArray<Dummy>(invalid_dummy_array, TryParseDummy, &out));
+ EXPECT_FALSE(TryParseArray<Dummy>(kEmptyArray, TryParseDummy, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateIntArray) {
+TEST(ParsingHelpersTest, TryParseIntArray) {
Json::Value valid_int_array;
valid_int_array[0] = 123;
valid_int_array[1] = 456;
@@ -174,13 +171,13 @@ TEST(ParsingHelpersTest, ParseAndValidateIntArray) {
invalid_int_array[1] = 456;
std::vector<int> out;
- EXPECT_TRUE(ParseAndValidateIntArray(valid_int_array, &out));
+ EXPECT_TRUE(TryParseIntArray(valid_int_array, &out));
EXPECT_THAT(out, ElementsAre(123, 456));
- EXPECT_FALSE(ParseAndValidateIntArray(invalid_int_array, &out));
- EXPECT_FALSE(ParseAndValidateIntArray(kEmptyArray, &out));
+ EXPECT_FALSE(TryParseIntArray(invalid_int_array, &out));
+ EXPECT_FALSE(TryParseIntArray(kEmptyArray, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateUintArray) {
+TEST(ParsingHelpersTest, TryParseUintArray) {
Json::Value valid_uint_array;
valid_uint_array[0] = 123u;
valid_uint_array[1] = 456u;
@@ -190,13 +187,13 @@ TEST(ParsingHelpersTest, ParseAndValidateUintArray) {
invalid_uint_array[1] = 456u;
std::vector<uint32_t> out;
- EXPECT_TRUE(ParseAndValidateUintArray(valid_uint_array, &out));
+ EXPECT_TRUE(TryParseUintArray(valid_uint_array, &out));
EXPECT_THAT(out, ElementsAre(123u, 456u));
- EXPECT_FALSE(ParseAndValidateUintArray(invalid_uint_array, &out));
- EXPECT_FALSE(ParseAndValidateUintArray(kEmptyArray, &out));
+ EXPECT_FALSE(TryParseUintArray(invalid_uint_array, &out));
+ EXPECT_FALSE(TryParseUintArray(kEmptyArray, &out));
}
-TEST(ParsingHelpersTest, ParseAndValidateStringArray) {
+TEST(ParsingHelpersTest, TryParseStringArray) {
Json::Value valid_string_array;
valid_string_array[0] = "nitro cold brew";
valid_string_array[1] = "doppio espresso";
@@ -206,10 +203,10 @@ TEST(ParsingHelpersTest, ParseAndValidateStringArray) {
invalid_string_array[1] = 456;
std::vector<std::string> out;
- EXPECT_TRUE(ParseAndValidateStringArray(valid_string_array, &out));
+ EXPECT_TRUE(TryParseStringArray(valid_string_array, &out));
EXPECT_THAT(out, ElementsAre("nitro cold brew", "doppio espresso"));
- EXPECT_FALSE(ParseAndValidateStringArray(invalid_string_array, &out));
- EXPECT_FALSE(ParseAndValidateStringArray(kEmptyArray, &out));
+ EXPECT_FALSE(TryParseStringArray(invalid_string_array, &out));
+ EXPECT_FALSE(TryParseStringArray(kEmptyArray, &out));
}
} // namespace json
diff --git a/util/simple_fraction.cc b/util/simple_fraction.cc
index a98d825c..46d2e585 100644
--- a/util/simple_fraction.cc
+++ b/util/simple_fraction.cc
@@ -33,37 +33,14 @@ ErrorOr<SimpleFraction> SimpleFraction::FromString(absl::string_view value) {
}
}
- return SimpleFraction{numerator, denominator};
+ return SimpleFraction(numerator, denominator);
}
std::string SimpleFraction::ToString() const {
- if (denominator == 1) {
- return std::to_string(numerator);
+ if (denominator_ == 1) {
+ return std::to_string(numerator_);
}
- return absl::StrCat(numerator, "/", denominator);
-}
-
-bool SimpleFraction::operator==(const SimpleFraction& other) const {
- return numerator == other.numerator && denominator == other.denominator;
-}
-
-bool SimpleFraction::operator!=(const SimpleFraction& other) const {
- return !(*this == other);
-}
-
-bool SimpleFraction::is_defined() const {
- return denominator != 0;
-}
-
-bool SimpleFraction::is_positive() const {
- return is_defined() && (numerator >= 0) && (denominator > 0);
-}
-
-SimpleFraction::operator double() const {
- if (denominator == 0) {
- return nan("");
- }
- return static_cast<double>(numerator) / static_cast<double>(denominator);
+ return absl::StrCat(numerator_, "/", denominator_);
}
} // namespace openscreen
diff --git a/util/simple_fraction.h b/util/simple_fraction.h
index f8ab5083..2df45e24 100644
--- a/util/simple_fraction.h
+++ b/util/simple_fraction.h
@@ -5,6 +5,8 @@
#ifndef UTIL_SIMPLE_FRACTION_H_
#define UTIL_SIMPLE_FRACTION_H_
+#include <cmath>
+#include <limits>
#include <string>
#include "absl/strings/string_view.h"
@@ -14,30 +16,56 @@ namespace openscreen {
// SimpleFraction is used to represent simple (or "common") fractions, composed
// of a rational number written a/b where a and b are both integers.
-
-// Note: Since SimpleFraction is a trivial type, it comes with a
-// default constructor and is copyable, as well as allowing static
-// initialization.
-
// Some helpful notes on SimpleFraction assumptions/limitations:
// 1. SimpleFraction does not perform reductions. 2/4 != 1/2, and -1/-1 != 1/1.
// 2. denominator = 0 is considered undefined.
// 3. numerator = saturates range to int min or int max
// 4. A SimpleFraction is "positive" if and only if it is defined and at least
// equal to zero. Since reductions are not performed, -1/-1 is negative.
-struct SimpleFraction {
+class SimpleFraction {
+ public:
static ErrorOr<SimpleFraction> FromString(absl::string_view value);
std::string ToString() const;
- bool operator==(const SimpleFraction& other) const;
- bool operator!=(const SimpleFraction& other) const;
+ constexpr SimpleFraction() = default;
+ constexpr SimpleFraction(int numerator) // NOLINT
+ : numerator_(numerator) {}
+ constexpr SimpleFraction(int numerator, int denominator)
+ : numerator_(numerator), denominator_(denominator) {}
+
+ constexpr SimpleFraction(const SimpleFraction&) = default;
+ constexpr SimpleFraction(SimpleFraction&&) noexcept = default;
+ constexpr SimpleFraction& operator=(const SimpleFraction&) = default;
+ constexpr SimpleFraction& operator=(SimpleFraction&&) = default;
+ ~SimpleFraction() = default;
+
+ constexpr bool operator==(const SimpleFraction& other) const {
+ return numerator_ == other.numerator_ && denominator_ == other.denominator_;
+ }
+
+ constexpr bool operator!=(const SimpleFraction& other) const {
+ return !(*this == other);
+ }
+
+ constexpr bool is_defined() const { return denominator_ != 0; }
+
+ constexpr bool is_positive() const {
+ return (numerator_ >= 0) && (denominator_ > 0);
+ }
+
+ constexpr explicit operator double() const {
+ if (denominator_ == 0) {
+ return nan("");
+ }
+ return static_cast<double>(numerator_) / static_cast<double>(denominator_);
+ }
- bool is_defined() const;
- bool is_positive() const;
- explicit operator double() const;
+ constexpr int numerator() const { return numerator_; }
+ constexpr int denominator() const { return denominator_; }
- int numerator = 0;
- int denominator = 0;
+ private:
+ int numerator_ = 0;
+ int denominator_ = 1;
};
} // namespace openscreen
diff --git a/util/stringprintf.cc b/util/stringprintf.cc
index 2d9bba22..49c29dc8 100644
--- a/util/stringprintf.cc
+++ b/util/stringprintf.cc
@@ -32,11 +32,11 @@ std::string StringPrintf(const char* format, ...) {
return result;
}
-std::string HexEncode(absl::Span<const uint8_t> bytes) {
+std::string HexEncode(const uint8_t* bytes, std::size_t len) {
std::ostringstream hex_dump;
hex_dump << std::setfill('0') << std::hex;
- for (const uint8_t byte : bytes) {
- hex_dump << std::setw(2) << static_cast<int>(byte);
+ for (std::size_t i = 0; i < len; i++) {
+ hex_dump << std::setw(2) << static_cast<int>(bytes[i]);
}
return hex_dump.str();
}
diff --git a/util/stringprintf.h b/util/stringprintf.h
index 0de394ea..23f07fea 100644
--- a/util/stringprintf.h
+++ b/util/stringprintf.h
@@ -10,12 +10,6 @@
#include <ostream>
#include <string>
-// TODO: This header is included in the openscreen discovery public headers (dns_sd_instance.h),
-// which exposes this abseil header. Need to figure out a way to hide it.
-#if 0
-#include "absl/types/span.h"
-#endif
-
namespace openscreen {
// Enable compile-time checking of the printf format argument, if available.
@@ -58,10 +52,8 @@ void PrettyPrintAsciiHex(std::ostream& os, It first, It last) {
}
}
-#if 0
// Returns a hex string representation of the given |bytes|.
-std::string HexEncode(absl::Span<const uint8_t> bytes);
-#endif
+std::string HexEncode(const uint8_t* bytes, std::size_t len);
} // namespace openscreen
diff --git a/util/stringprintf_unittest.cc b/util/stringprintf_unittest.cc
index e37e7cb6..bf882163 100644
--- a/util/stringprintf_unittest.cc
+++ b/util/stringprintf_unittest.cc
@@ -20,13 +20,13 @@ TEST(StringPrintf, ProducesFormattedStrings) {
TEST(HexEncode, ProducesEmptyStringFromEmptyByteArray) {
const uint8_t kSomeMemoryLocation = 0;
- EXPECT_EQ("", HexEncode(absl::Span<const uint8_t>(&kSomeMemoryLocation, 0)));
+ EXPECT_EQ("", HexEncode(&kSomeMemoryLocation, 0));
}
TEST(HexEncode, ProducesHexStringsFromBytes) {
const uint8_t kMessage[] = "Hello world!";
const char kMessageInHex[] = "48656c6c6f20776f726c642100";
- EXPECT_EQ(kMessageInHex, HexEncode(kMessage));
+ EXPECT_EQ(kMessageInHex, HexEncode(kMessage, sizeof(kMessage)));
}
} // namespace