diff --git a/include/sexpp/sexp.h b/include/sexpp/sexp.h index bb6ae4e..3bba921 100644 --- a/include/sexpp/sexp.h +++ b/include/sexpp/sexp.h @@ -99,14 +99,69 @@ class sexp_input_stream_t; * SEXP simple string */ -typedef uint8_t octet_t; +using octet_t = uint8_t; -class SEXP_PUBLIC_SYMBOL sexp_simple_string_t : public std::basic_string, - private sexp_char_defs_t { +struct octet_traits : std::char_traits { + static void assign(char_type &r, const char_type &a) { r = a; } + + static bool eq(const char_type &c1, const char_type &c2) { return c1 == c2; } + + static bool lt(const char_type &c1, const char_type &c2) { return c1 < c2; } + + static int compare(const char_type *s1, const char_type *s2, std::size_t n) + { + while (n-- != 0) { + if (*s1 < *s2) + return -1; + if (*s2++ < *s1++) + return 1; + } + return 0; + } + + static const char_type *find(const char_type *s, std::size_t n, const char_type &a) + { + while (n-- != 0) { + if (*s == a) + return s; + s++; + } + return nullptr; + } + + static char_type *move(char_type *s1, const char_type *s2, std::size_t n) + { + return (char_type *) std::memmove(s1, s2, n); + } + + static char_type *copy(char_type *s1, const char_type *s2, std::size_t n) + { + return (char_type *) std::memcpy(s1, s2, n); + } + + static char_type *assign(char_type *s, std::size_t n, char_type a) + { + return (char_type *) std::memset(s, a, n); + } + + static char_type to_char_type(const int_type &c) { return char_type(c); } + + static int_type to_int_type(const char_type &c) { return int_type(c); } + + static bool eq_int_type(const int_type &c1, const int_type &c2) { return c1 == c2; } + + static int_type eof() { return static_cast(EOF); } + + static int_type not_eof(const int_type &c) { return eq_int_type(c, eof()) ? 0 : c; } +}; + +using octet_string = std::basic_string; + +class SEXP_PUBLIC_SYMBOL sexp_simple_string_t : public octet_string, private sexp_char_defs_t { public: sexp_simple_string_t(void) = default; - sexp_simple_string_t(const octet_t *dt) : std::basic_string{dt} {} - sexp_simple_string_t(const octet_t *bt, size_t ln) : std::basic_string{bt, ln} {} + sexp_simple_string_t(const octet_t *dt) : octet_string{dt} {} + sexp_simple_string_t(const octet_t *bt, size_t ln) : octet_string{bt, ln} {} sexp_simple_string_t &append(int c) { (*this) += (octet_t)(c & 0xFF); diff --git a/tests/src/traits-tests.cpp b/tests/src/traits-tests.cpp new file mode 100644 index 0000000..52e1019 --- /dev/null +++ b/tests/src/traits-tests.cpp @@ -0,0 +1,116 @@ +/** + * + * Copyright 2024 Ribose Inc. (https://www.ribose.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "sexp-tests.h" + +using namespace sexp; + +namespace { + +TEST(OctetTraitsTest, Assign) +{ + octet_t a = 0x12; + octet_t b = 0x34; + octet_traits::assign(a, b); + EXPECT_EQ(a, b); +} + +TEST(OctetTraitsTest, Eq) +{ + octet_t a = 0x12; + octet_t b = 0x12; + EXPECT_TRUE(octet_traits::eq(a, b)); +} + +TEST(OctetTraitsTest, Lt) +{ + octet_t a = 0x12; + octet_t b = 0x34; + EXPECT_TRUE(octet_traits::lt(a, b)); +} + +TEST(OctetTraitsTest, Compare) +{ + octet_t s1[] = {0x12, 0x34, 0x56}; + octet_t s2[] = {0x12, 0x34, 0x57}; + EXPECT_LT(octet_traits::compare(s1, s2, 3), 0); +} + +TEST(OctetTraitsTest, Find) +{ + octet_t s[] = {0x12, 0x34, 0x56}; + octet_t a = 0x34; + EXPECT_EQ(octet_traits::find(s, 3, a), s + 1); +} + +TEST(OctetTraitsTest, Move) +{ + octet_t s1[] = {0x12, 0x34, 0x56}; + octet_t s2[3]; + octet_traits::move(s2, s1, 3); + EXPECT_EQ(memcmp(s1, s2, 3), 0); +} + +TEST(OctetTraitsTest, Copy) +{ + octet_t s1[] = {0x12, 0x34, 0x56}; + octet_t s2[3]; + octet_traits::copy(s2, s1, 3); + EXPECT_EQ(memcmp(s1, s2, 3), 0); +} + +TEST(OctetTraitsTest, AssignMultiple) +{ + octet_t s[3]; + octet_t a = 0x12; + octet_traits::assign(s, 3, a); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(s[i], a); + } +} + +TEST(OctetTraitsTest, ToCharType) +{ + octet_traits::int_type a = 0x12; + EXPECT_EQ(octet_traits::to_char_type(a), 0x12); +} + +TEST(OctetTraitsTest, ToIntType) +{ + octet_t a = 0x12; + EXPECT_EQ(octet_traits::to_int_type(a), 0x12); +} + +TEST(OctetTraitsTest, EqIntType) +{ + octet_traits::int_type a = 0x12; + octet_traits::int_type b = 0x12; + EXPECT_TRUE(octet_traits::eq_int_type(a, b)); +} + +TEST(OctetTraitsTest, NotEof) +{ + octet_traits::int_type a = 0x12; + EXPECT_EQ(octet_traits::not_eof(a), 0x12); +} +} // namespace diff --git a/version.txt b/version.txt index 1e9b46b..6201b5f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.8.7 +0.8.8