Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented char_traits for SEXP octet_t #54

Merged
merged 2 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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', 'tgagor/centos:stream8', 'quay.io/centos/centos:stream9', 'fedora:35', 'fedora:36', 'fedora:38' ]
image: [ 'centos:7', 'quay.io/centos/centos:stream9', 'fedora:35', 'fedora:36', 'fedora:38']
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
Loading