Skip to content

Commit

Permalink
Replaced string<octet_t> with vector<octet_t> to adhere to C++ standa…
Browse files Browse the repository at this point in the history
…rd (#51)
  • Loading branch information
maxirmx committed Jun 1, 2024
1 parent 2c8d9f4 commit bce04bb
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 51 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/build-and-test-rh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ jobs:
run: sudo yum -y install findutils

- name: Checkout shell test framework
if: matrix.image != 'centos:7'
uses: actions/checkout@v4
with:
repository: kward/shunit2
path: ${{github.workspace}}/tests/shunit2
fetch-depth: 1

- name: Checkout shell test framework centos7
if: matrix.image == 'centos:7'
uses: actions/checkout@v3
with:
repository: kward/shunit2
Expand Down
7 changes: 4 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ if (BUILD_SHARED_LIBS AND MSVC)
message(FATAL_ERROR "Building sexp shared library with MSVC is not supported")
endif(BUILD_SHARED_LIBS AND MSVC)


message(STATUS "Building ${TYPE} library")

if (WITH_SANITIZERS)
Expand Down Expand Up @@ -107,7 +106,6 @@ if(NOT MSVC)
-Wno-unused-parameter
-Wno-missing-field-initializers
)

endif(NOT MSVC)

add_library(sexpp ${TYPE}
Expand All @@ -132,7 +130,10 @@ target_include_directories(sexpp PUBLIC

if (BUILD_SHARED_LIBS)
target_compile_definitions(sexpp PUBLIC BUILD_SHARED_LIBS)
set_target_properties(sexpp PROPERTIES CXX_VISIBILITY_PRESET "hidden")
set_target_properties(sexpp PROPERTIES
CXX_VISIBILITY_PRESET "hidden"
VISIBILITY_INLINES_HIDDEN true
)
endif (BUILD_SHARED_LIBS)

set_target_properties(sexpp PROPERTIES
Expand Down
36 changes: 17 additions & 19 deletions include/sexpp/sexp.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,25 @@ class sexp_input_stream_t;

typedef uint8_t octet_t;

class SEXP_PUBLIC_SYMBOL sexp_simple_string_t : public std::basic_string<octet_t>,
class SEXP_PUBLIC_SYMBOL sexp_simple_string_t : public std::vector<octet_t>,
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) : std::vector<octet_t>() { for (; *dt; ++dt) push_back(*dt); }
sexp_simple_string_t(const octet_t *bt, size_t ln) : std::vector<octet_t>(ln) { for (size_t s = 0; s < ln; ++bt, ++s ) push_back(*bt); }
sexp_simple_string_t &append(int c)
{
(*this) += (octet_t)(c & 0xFF);
push_back((octet_t)(c & 0xFF));
return *this;
}
// Returns length for printing simple string as a token
size_t advanced_length_token(void) const { return length(); }
size_t advanced_length_token(void) const { return size(); }
// Returns length for printing simple string as a base64 string
size_t advanced_length_base64(void) const { return (2 + 4 * ((length() + 2) / 3)); }
size_t advanced_length_base64(void) const { return (2 + 4 * ((size() + 2) / 3)); }
// Returns length for printing simple string ss in quoted-string mode
size_t advanced_length_quoted(void) const { return (1 + length() + 1); }
size_t advanced_length_quoted(void) const { return (1 + size() + 1); }
// Returns length for printing simple string ss in hexadecimal mode
size_t advanced_length_hexadecimal(void) const { return (1 + 2 * length() + 1); }
size_t advanced_length_hexadecimal(void) const { return (1 + 2 * size() + 1); }
size_t advanced_length(sexp_output_stream_t *os) const;

sexp_output_stream_t *print_canonical_verbatim(sexp_output_stream_t *os) const;
Expand All @@ -134,19 +134,15 @@ class SEXP_PUBLIC_SYMBOL sexp_simple_string_t : public std::basic_string<octet_t

bool operator==(const char *right) const noexcept
{
return length() == std::strlen(right) && std::memcmp(data(), right, length()) == 0;
return size() == std::strlen(right) && std::memcmp(data(), right, size()) == 0;
}

bool operator!=(const char *right) const noexcept
{
return length() != std::strlen(right) || std::memcmp(data(), right, length()) != 0;
return size() != std::strlen(right) || std::memcmp(data(), right, size()) != 0;
}

unsigned as_unsigned() const noexcept
{
return empty() ? std::numeric_limits<uint32_t>::max() :
(unsigned) atoi(reinterpret_cast<const char *>(c_str()));
}
uint32_t as_unsigned() const noexcept;
};

inline bool operator==(const sexp_simple_string_t *left, const std::string &right) noexcept
Expand Down Expand Up @@ -193,7 +189,7 @@ class SEXP_PUBLIC_SYMBOL sexp_object_t {
}
virtual bool operator==(const char *right) const noexcept { return false; }
virtual bool operator!=(const char *right) const noexcept { return true; }
virtual unsigned as_unsigned() const noexcept
virtual uint32_t as_unsigned() const noexcept
{
return std::numeric_limits<uint32_t>::max();
}
Expand Down Expand Up @@ -250,17 +246,19 @@ class SEXP_PUBLIC_SYMBOL sexp_string_t : public sexp_object_t {
virtual bool operator!=(const char *right) const noexcept { return data_string != right; }

void parse(sexp_input_stream_t *sis);
virtual unsigned as_unsigned() const noexcept { return data_string.as_unsigned(); }
virtual uint32_t as_unsigned() const noexcept { return data_string.as_unsigned(); }
};

inline bool operator==(const sexp_string_t *left, const std::string &right) noexcept
{
return *left == right.c_str();
return left->get_string().size() == right.length() &&
memcmp(left->get_string().data(), right.c_str(), left->get_string().size()) == 0;
}

inline bool operator!=(const sexp_string_t *left, const std::string &right) noexcept
{
return *left != right.c_str();
return left->get_string().size() != right.length() ||
memcmp(left->get_string().data(), right.c_str(), left->get_string().size()) != 0;
}

/*
Expand Down
14 changes: 7 additions & 7 deletions src/sexp-input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,9 @@ void sexp_input_stream_t::scan_verbatim_string(sexp_simple_string_t &ss, uint32_
void sexp_input_stream_t::scan_quoted_string(sexp_simple_string_t &ss, uint32_t length)
{
skip_char('"');
while (ss.length() <= length) {
while (ss.size() <= length) {
if (next_char == '\"') {
if (length == std::numeric_limits<uint32_t>::max() || (ss.length() == length)) {
if (length == std::numeric_limits<uint32_t>::max() || (ss.size() == length)) {
skip_char('\"');
return;
} else
Expand Down Expand Up @@ -367,10 +367,10 @@ void sexp_input_stream_t::scan_hexadecimal_string(sexp_simple_string_t &ss, uint
get_char();
}
skip_char('#');
if (ss.length() != length && length != std::numeric_limits<uint32_t>::max())
if (ss.size() != length && length != std::numeric_limits<uint32_t>::max())
sexp_error(sexp_exception_t::warning,
"Hex string has length %d different than declared length %d",
ss.length(),
ss.size(),
length,
count);
}
Expand All @@ -389,10 +389,10 @@ void sexp_input_stream_t::scan_base64_string(sexp_simple_string_t &ss, uint32_t
get_char();
}
skip_char('|');
if (ss.length() != length && length != std::numeric_limits<uint32_t>::max())
if (ss.size() != length && length != std::numeric_limits<uint32_t>::max())
sexp_error(sexp_exception_t::warning,
"Base64 string has length %d different than declared length %d",
ss.length(),
ss.size(),
length,
count);
}
Expand Down Expand Up @@ -441,7 +441,7 @@ sexp_simple_string_t sexp_input_stream_t::scan_simple_string(void)
}
}

if (ss.length() == 0)
if (ss.size() == 0)
sexp_error(sexp_exception_t::warning, "Simple string has zero length", 0, 0, count);
return ss;
}
Expand Down
81 changes: 61 additions & 20 deletions src/sexp-simple-string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,39 @@
#include "sexpp/sexp.h"

namespace sexp {

/*
* sexp_simple_string_t::sexp_simple_string_t(const octet_t *dt)
*/
sexp_simple_string_t::sexp_simple_string_t(const octet_t *dt) : std::vector<octet_t>()
{
for (; *dt; ++dt)
push_back(*dt);
}

/*
* sexp_simple_string_t::sexp_simple_string_t(const octet_t *bt, size_t ln)
*/
sexp_simple_string_t::sexp_simple_string_t(const octet_t *bt, size_t ln)
: std::vector<octet_t>()
{
reserve(ln);
for (size_t s = 0; s < ln; ++bt, ++s)
push_back(*bt);
}

/*
* sexp_simple_string_t::print_canonical_verbatim(os)
* Print out simple string on output stream os as verbatim string.
*/
sexp_output_stream_t *sexp_simple_string_t::print_canonical_verbatim(
sexp_output_stream_t *os) const
{
const octet_t *c = c_str();
const octet_t *c = data();
/* print out len: */
os->print_decimal(length())->var_put_char(':');
os->print_decimal(size())->var_put_char(':');
/* print characters in fragment */
for (uint32_t i = 0; i < length(); i++)
for (uint32_t i = 0; i < size(); i++)
os->var_put_char((int) *c++);
return os;
}
Expand All @@ -55,25 +76,45 @@ size_t sexp_simple_string_t::advanced_length(sexp_output_stream_t *os) const
return advanced_length_token();
else if (can_print_as_quoted_string())
return advanced_length_quoted();
else if (length() <= 4 && os->get_byte_size() == 8)
else if (size() <= 4 && os->get_byte_size() == 8)
return advanced_length_hexadecimal();
else if (os->get_byte_size() == 8)
return advanced_length_base64();
else
return 0; /* an error condition */
}

/*
* sexp_simple_string_t::as_unsigned
* Converts simple string to unsigned integer.
* Returns std::numeric_limits<uint32_t>::max() if simple string is empty
* Returns 0 if simple string contains non-digit characters
*/
uint32_t sexp_simple_string_t::as_unsigned() const noexcept
{
if (empty())
return std::numeric_limits<uint32_t>::max();

uint32_t result = 0;
for (octet_t c : *this) {
if (!is_dec_digit(c))
return 0;
result = result * 10 + (c - '0');
}
return result;
}

/*
* sexp_simple_string_t::print_token(os)
* Prints out simple string ss as a token (assumes that this is OK).
* May run over max-column, but there is no fragmentation allowed...
*/
sexp_output_stream_t *sexp_simple_string_t::print_token(sexp_output_stream_t *os) const
{
const octet_t *c = c_str();
if (os->get_max_column() > 0 && os->get_column() > (os->get_max_column() - length()))
const octet_t *c = data();
if (os->get_max_column() > 0 && os->get_column() > (os->get_max_column() - size()))
os->new_line(sexp_output_stream_t::advanced);
for (uint32_t i = 0; i < length(); i++)
for (uint32_t i = 0; i < size(); i++)
os->put_char((int) (*c++));
return os;
}
Expand All @@ -84,9 +125,9 @@ sexp_output_stream_t *sexp_simple_string_t::print_token(sexp_output_stream_t *os
*/
sexp_output_stream_t *sexp_simple_string_t::print_base64(sexp_output_stream_t *os) const
{
const octet_t *c = c_str();
const octet_t *c = data();
os->var_put_char('|')->change_output_byte_size(6, sexp_output_stream_t::advanced);
for (uint32_t i = 0; i < length(); i++)
for (uint32_t i = 0; i < size(); i++)
os->var_put_char((int) (*c++));
return os->flush()
->change_output_byte_size(8, sexp_output_stream_t::advanced)
Expand All @@ -99,9 +140,9 @@ sexp_output_stream_t *sexp_simple_string_t::print_base64(sexp_output_stream_t *o
*/
sexp_output_stream_t *sexp_simple_string_t::print_hexadecimal(sexp_output_stream_t *os) const
{
const octet_t *c = c_str();
const octet_t *c = data();
os->put_char('#')->change_output_byte_size(4, sexp_output_stream_t::advanced);
for (uint32_t i = 0; i < length(); i++)
for (uint32_t i = 0; i < size(); i++)
os->var_put_char((int) (*c++));
return os->flush()
->change_output_byte_size(8, sexp_output_stream_t::advanced)
Expand All @@ -117,9 +158,9 @@ sexp_output_stream_t *sexp_simple_string_t::print_hexadecimal(sexp_output_stream
*/
sexp_output_stream_t *sexp_simple_string_t::print_quoted(sexp_output_stream_t *os) const
{
const octet_t *c = c_str();
const octet_t *c = data();
os->put_char('\"');
for (uint32_t i = 0; i < length(); i++) {
for (uint32_t i = 0; i < size(); i++) {
if (os->get_max_column() > 0 && os->get_column() >= os->get_max_column() - 2) {
os->put_char('\\')->put_char('\n');
os->reset_column();
Expand All @@ -139,7 +180,7 @@ sexp_output_stream_t *sexp_simple_string_t::print_advanced(sexp_output_stream_t
print_token(os);
else if (can_print_as_quoted_string())
print_quoted(os);
else if (length() <= 4 && os->get_byte_size() == 8)
else if (size() <= 4 && os->get_byte_size() == 8)
print_hexadecimal(os);
else if (os->get_byte_size() == 8)
print_base64(os);
Expand All @@ -159,8 +200,8 @@ sexp_output_stream_t *sexp_simple_string_t::print_advanced(sexp_output_stream_t
*/
bool sexp_simple_string_t::can_print_as_quoted_string(void) const
{
const octet_t *c = c_str();
for (uint32_t i = 0; i < length(); i++, c++) {
const octet_t *c = data();
for (uint32_t i = 0; i < size(); i++, c++) {
if (!is_token_char((int) (*c)) && *c != ' ')
return false;
}
Expand All @@ -174,14 +215,14 @@ bool sexp_simple_string_t::can_print_as_quoted_string(void) const
*/
bool sexp_simple_string_t::can_print_as_token(const sexp_output_stream_t *os) const
{
const octet_t *c = c_str();
if (length() <= 0)
const octet_t *c = data();
if (size() <= 0)
return false;
if (is_dec_digit((int) *c))
return false;
if (os->get_max_column() > 0 && os->get_column() + length() >= os->get_max_column())
if (os->get_max_column() > 0 && os->get_column() + size() >= os->get_max_column())
return false;
for (uint32_t i = 0; i < length(); i++) {
for (uint32_t i = 0; i < size(); i++) {
if (!is_token_char((int) (*c++)))
return false;
}
Expand Down
23 changes: 22 additions & 1 deletion tests/src/primitives-tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ TEST_F(PrimitivesTests, at4rnp)
}

const sexp_string_t *sstr = lst.sexp_string_at(0);
EXPECT_STREQ(reinterpret_cast<const char *>(sstr->get_string().c_str()), "rnp_block");
int result = memcmp(sstr->get_string().data(), "rnp_block", sstr->get_string().size());
EXPECT_EQ(result, 0);
}

TEST_F(PrimitivesTests, eq4rnp)
Expand Down Expand Up @@ -280,6 +281,15 @@ TEST_F(PrimitivesTests, u4rnp)
EXPECT_EQ(lst.sexp_string_at(1)->as_unsigned(), 54321);
}

TEST_F(PrimitivesTests, asUnsigned)
{
sexp_simple_string_t sss1(reinterpret_cast<const octet_t *>(""));
EXPECT_EQ(sss1.as_unsigned(), std::numeric_limits<uint32_t>::max());

sexp_simple_string_t sss2(reinterpret_cast<const octet_t *>("123A456"));
EXPECT_EQ(sss2.as_unsigned(), 0);
}

TEST_F(PrimitivesTests, proInheritance)
{
sexp_list_t lst;
Expand Down Expand Up @@ -391,4 +401,15 @@ TEST_F(PrimitivesTests, EnsureHexTest)
EXPECT_EQ(oss.str(), "(#610963#)");
}

TEST_F(PrimitivesTests, SimpleStringConstructors)
{
const char *tss = "test simple string";

sexp_simple_string_t sss1(reinterpret_cast<const octet_t *>(tss));
EXPECT_TRUE(sss1 == tss);

sexp_simple_string_t sss2(reinterpret_cast<const octet_t *>(tss), 4);
EXPECT_TRUE(sss2 == "test");
}

} // 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.9.0

0 comments on commit bce04bb

Please sign in to comment.