Skip to content

Commit

Permalink
Implemented char_traits for SEXP octet_t
Browse files Browse the repository at this point in the history
  • Loading branch information
maxirmx committed Jun 6, 2024
1 parent 00fc6b5 commit 35a13f9
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-rh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
strategy:
fail-fast: false
matrix:
image: [ 'centos:7', 'quay.io/centos/centos:stream9', 'fedora:35', 'fedora:36', 'fedora:38' ]
image: [ 'centos:7', 'quay.io/centos/centos:stream9', 'fedora:35', 'fedora:36']
env: [ {CC: gcc, CXX: g++}, {CC: clang, CXX: clang++} ]
shared: [ on, off ]
container: ${{ matrix.image }}
Expand Down
95 changes: 90 additions & 5 deletions include/sexpp/sexp.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,93 @@
#include "sexp-public.h"
#include "sexp-error.h"

// We are implementing char traits for octet_t with trhe following restrictions
// -- limit visibility so that other traits for unsigned char are still possible
// -- create template specializatio in std workspace (use workspace specialization
// is not specified and causes issues at least with gcc 4.8

namespace sexp {
using octet_t = uint8_t;
} // namespace sexp

namespace std {

template <> struct char_traits<sexp::octet_t> {
typedef sexp::octet_t char_type;
typedef int int_type;
typedef std::streampos pos_type;
typedef std::streamoff off_type;
typedef mbstate_t state_type;

static void assign(char_type &__c1, const char_type &__c2) noexcept { __c1 = __c2; }

static constexpr bool eq(const char_type &__c1, const char_type &__c2) noexcept
{
return __c1 == __c2;
}

static constexpr bool lt(const char_type &__c1, const char_type &__c2) noexcept
{
return __c1 < __c2;
}

static int compare(const char_type *__s1, const char_type *__s2, size_t __n)
{
return memcmp(__s1, __s2, __n);
}

static size_t length(const char_type *__s)
{
return strlen(reinterpret_cast<const char *>(__s));
}

static const char_type *find(const char_type *__s, size_t __n, const char_type &__a)
{
return static_cast<const char_type *>(memchr(__s, __a, __n));
}

static char_type *move(char_type *__s1, const char_type *__s2, size_t __n)
{
return static_cast<char_type *>(memmove(__s1, __s2, __n));
}

static char_type *copy(char_type *__s1, const char_type *__s2, size_t __n)
{
return static_cast<char_type *>(memcpy(__s1, __s2, __n));
}

static char_type *assign(char_type *__s, size_t __n, char_type __a)
{
return static_cast<char_type *>(memset(__s, __a, __n));
}

static constexpr char_type to_char_type(const int_type &__c) noexcept
{
return static_cast<char_type>(__c);
}

// To keep both the byte 0xff and the eof symbol 0xffffffff
// from ending up as 0xffffffff.
static constexpr int_type to_int_type(const char_type &__c) noexcept
{
return static_cast<int_type>(static_cast<unsigned char>(__c));
}

static constexpr bool eq_int_type(const int_type &__c1, const int_type &__c2) noexcept
{
return __c1 == __c2;
}

static constexpr int_type eof() noexcept { return static_cast<int_type>(0xFFFFFFFF); }

static constexpr int_type not_eof(const int_type &__c) noexcept
{
return (__c == eof()) ? 0 : __c;
}
};
} // namespace std

namespace sexp {
/*
* SEXP octet_t definitions
* We maintain some presumable redundancy with ctype
Expand Down Expand Up @@ -99,14 +184,14 @@ class sexp_input_stream_t;
* SEXP simple string
*/

typedef uint8_t octet_t;
using octet_traits = std::char_traits<octet_t>;
using octet_string = std::basic_string<octet_t, octet_traits>;

class SEXP_PUBLIC_SYMBOL sexp_simple_string_t : public std::basic_string<octet_t>,
private sexp_char_defs_t {
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<octet_t>{dt} {}
sexp_simple_string_t(const octet_t *bt, size_t ln) : std::basic_string<octet_t>{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);
Expand Down
116 changes: 116 additions & 0 deletions tests/src/traits-tests.cpp
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.8.7
0.8.8

0 comments on commit 35a13f9

Please sign in to comment.