Program Listing for File base_string.hpp
↰ Return to documentation for file (/tmp/ws/src/apex_containers/apex_containers/include/string/base_string.hpp
)
// Copyright 2017-2018 Apex.AI, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef STRING__BASE_STRING_HPP_
#define STRING__BASE_STRING_HPP_
#include <apexutils/apexdef.h>
#include <apex_containers/visibility_control.hpp>
#include <stdexcept>
#include <climits>
#include <cstring>
#include <algorithm>
#include <istream>
#include <ostream>
#include <string>
namespace apex
{
template<::size64_t BUFFER_SIZE>
class BaseString
{
public:
using char_type = char8_t;
BaseString(void) noexcept
{
// Ignore unneeded pointer to destination
(void)::memset(&(this->m_string[0U]), 0, this->get_buffer_size());
}
constexpr static const ::size64_t npos = ULLONG_MAX;
constexpr const ::char8_t * data() const noexcept
{
return &(m_string[0U]);
}
BaseString substr(const ::size64_t pos = 0U, const ::size64_t len = npos) const
{
BaseString retval;
::size64_t my_size = size();
if (pos > my_size) {
throw std::out_of_range("pos > my_size");
}
if (pos != my_size) {
const ::size64_t chars_to_copy = std::min(my_size - pos, len);
// Ignore unneeded returned pointer
(void)memmove(retval.m_string, m_string + pos, chars_to_copy);
}
return retval;
}
// Comparisons
int32_t compare(
const ::size64_t pos1,
const ::size64_t count1,
const ::char8_t * const s,
const ::size64_t count2 = npos) const
{
if (nullptr == s) {
throw std::invalid_argument("s == NULL");
}
const ::size64_t my_size = length();
if (pos1 > my_size) {
throw std::out_of_range("pos > my_len");
}
const ::size64_t _count1 = (npos == count1) ? my_size : count1;
::size64_t n_str = count2;
if (npos == count2) {
n_str = ::strnlen(s, APEX_STRING_SIZE);
}
const ::size64_t rlen = std::min(_count1, my_size - pos1);
int32_t cmp_retval = ::strncmp(data() + pos1, s, std::min(rlen, n_str));
if (cmp_retval == 0) {
if (rlen < n_str) {
cmp_retval = -1;
}
if (rlen > n_str) {
cmp_retval = 1;
}
}
return cmp_retval;
}
inline int32_t compare(const ::char8_t * const s) const
{
return this->compare(0U, npos, s);
}
bool operator==(const char8_t * const rhs) const
{
return this->compare(rhs) == 0;
}
template<::size64_t LEN>
int32_t compare(
const ::size64_t pos1,
const ::size64_t count1,
const BaseString<LEN> & str) const
{
return compare(pos1, count1, str.c_str());
}
int32_t compare(
const ::size64_t pos1,
const ::size64_t count1,
const std::string & str) const
{
return compare(pos1, count1, str.c_str());
}
template<::size64_t LEN>
int32_t compare(const BaseString<LEN> & str) const
{
return compare(0U, npos, str);
}
int32_t compare(const std::string & str) const
{
return compare(0U, npos, str);
}
template<::size64_t LEN>
bool operator==(const BaseString<LEN> & rhs) const
{
const int32_t cmp_retval = compare(0U, npos, rhs);
return cmp_retval == 0;
}
bool operator==(const std::string & rhs) const
{
const int32_t cmp_retval = compare(0U, npos, rhs.c_str());
return cmp_retval == 0;
}
bool operator!=(const char8_t * const rhs) const
{
return !operator==(rhs);
}
template<::size64_t LEN>
bool operator!=(const BaseString<LEN> & rhs) const
{
return !operator==(rhs);
}
bool operator!=(const std::string & rhs) const
{
return !operator==(rhs);
}
bool operator<(const char8_t * const rhs) const
{
return this->compare(rhs) < 0;
}
template<::size64_t LEN>
bool operator<(const BaseString<LEN> & rhs) const
{
const int32_t cmp_retval = compare(0U, npos, rhs);
return cmp_retval < 0;
}
bool operator<(const std::string & rhs) const
{
const int32_t cmp_retval = compare(0U, npos, rhs);
return cmp_retval < 0;
}
bool operator<=(const char8_t * const rhs) const
{
return !operator>(rhs);
}
template<::size64_t LEN>
bool operator<=(const BaseString<LEN> & rhs) const
{
return !operator>(rhs);
}
bool operator<=(const std::string & rhs) const
{
return !operator>(rhs);
}
bool operator>(const char8_t * const rhs) const
{
return this->compare(rhs) > 0;
}
template<::size64_t LEN>
bool operator>(const BaseString<LEN> & rhs) const
{
const int32_t cmp_retval = compare(0U, npos, rhs);
return cmp_retval > 0;
}
bool operator>(const std::string & rhs) const
{
const int32_t cmp_retval = compare(0U, npos, rhs);
return cmp_retval > 0;
}
bool operator>=(const char8_t * const rhs) const
{
return !operator<(rhs);
}
template<size64_t LEN>
bool operator>=(const BaseString<LEN> & rhs) const
{
return !operator<(rhs);
}
bool operator>=(const std::string & rhs) const
{
return !operator<(rhs);
}
// Getters
bool empty() const noexcept {return m_string[0U] == '\0';}
const char8_t * c_str() const noexcept
{
return m_string;
}
char8_t * data() noexcept
{
return &m_string[0];
}
inline constexpr size64_t capacity() const
{
return get_buffer_size() - 1U;
}
size64_t size() const noexcept
{
return ::strnlen(m_string, this->capacity());
}
size64_t length() const noexcept
{
return size();
}
char8_t & operator[](size64_t idx)
{
if (idx >= get_buffer_size()) {
throw std::out_of_range("idx >= get_buffer_size()");
}
return m_string[idx];
}
char8_t operator[](size64_t idx) const
{
if (idx >= get_buffer_size()) {
throw std::out_of_range("idx >= get_buffer_size()");
}
return m_string[idx];
}
inline constexpr ::size64_t get_buffer_size() const noexcept
{
return BUFFER_SIZE;
}
static inline constexpr ::size64_t get_buffer_size_static() noexcept
{
return BUFFER_SIZE;
}
operator std::string() const
{
return std::string(this->m_string);
}
// Removes all elements.
void clear() noexcept
{
(void)std::memset(&(this->m_string[0U]), 0, this->get_buffer_size());
}
protected:
// The apex::BaseString iterator abs_iterator class below is based on
// stackoverflow.com/questions/12092448/code-for-a-basic-random-access-iterator-based-on-pointers
// This class is for internal apex::string use only
template<typename Type>
class abs_iterator : public std::iterator<std::random_access_iterator_tag, Type>
{
public:
using difference_type =
typename std::iterator<std::random_access_iterator_tag, Type>::difference_type;
abs_iterator()
: m_ptr(nullptr)
{
}
explicit abs_iterator(Type * rhs)
: m_ptr(rhs)
{
}
abs_iterator(const abs_iterator & rhs)
: m_ptr(rhs.m_ptr)
{
}
inline abs_iterator & operator+=(difference_type rhs)
{
m_ptr += rhs; return *this;
}
inline abs_iterator & operator-=(difference_type rhs)
{
m_ptr -= rhs; return *this;
}
inline Type & operator*() const
{
return *m_ptr;
}
inline Type * operator->() const
{
return m_ptr;
}
inline Type & operator[](difference_type rhs)
{
return m_ptr[rhs];
}
inline const Type & operator[](difference_type rhs) const
{
return m_ptr[rhs];
}
inline abs_iterator & operator++()
{
++m_ptr; return *this;
}
inline abs_iterator & operator--()
{
--m_ptr; return *this;
}
inline abs_iterator operator++(int)
{
abs_iterator tmp(*this); ++m_ptr; return tmp;
}
inline abs_iterator operator--(int)
{
abs_iterator tmp(*this); --m_ptr; return tmp;
}
inline difference_type operator-(const abs_iterator & rhs) const
{
return difference_type(m_ptr - rhs.m_ptr);
}
inline abs_iterator operator+(difference_type rhs) const
{
return abs_iterator(m_ptr + rhs);
}
inline abs_iterator operator-(difference_type rhs) const
{
return abs_iterator(m_ptr - rhs);
}
friend inline abs_iterator operator+(difference_type lhs, const abs_iterator & rhs)
{
return abs_iterator(lhs + rhs.m_ptr);
}
friend inline abs_iterator operator-(difference_type lhs, const abs_iterator & rhs)
{
return abs_iterator(lhs - rhs.m_ptr);
}
inline bool operator==(const abs_iterator & rhs) const
{
return m_ptr == rhs.m_ptr;
}
inline bool operator!=(const abs_iterator & rhs) const
{
return m_ptr != rhs.m_ptr;
}
inline bool operator>(const abs_iterator & rhs) const
{
return m_ptr > rhs.m_ptr;
}
inline bool operator<(const abs_iterator & rhs) const
{
return m_ptr < rhs.m_ptr;
}
inline bool operator>=(const abs_iterator & rhs) const
{
return m_ptr >= rhs.m_ptr;
}
inline bool operator<=(const abs_iterator & rhs) const
{
return m_ptr <= rhs.m_ptr;
}
private:
Type * m_ptr;
};
char8_t m_string[BUFFER_SIZE];
};
template<size64_t STRING_BUFFER_SIZE>
typename ::std::basic_ostream<char8_t> & operator<<(
std::basic_ostream<char8_t> & out_stream,
const apex::BaseString<STRING_BUFFER_SIZE> & str)
{
return out_stream.write(str.c_str(), static_cast<std::streamsize>(str.size()));
}
template<::size64_t STRING_BUFFER_SIZE>
inline ::float32_t stof(const apex::BaseString<STRING_BUFFER_SIZE> & str) noexcept
{
const float32_t value = strtof(str.c_str(), nullptr);
return value;
}
template<::size64_t STRING_BUFFER_SIZE>
inline ::float64_t stod(const apex::BaseString<STRING_BUFFER_SIZE> & str) noexcept
{
const float64_t value = strtod(str.c_str(), nullptr);
return value;
}
template<::size64_t STRING_BUFFER_SIZE>
inline ::int32_t stol(const apex::BaseString<STRING_BUFFER_SIZE> & str) noexcept
{
::int64_t value = ::strtol(str.c_str(), nullptr, 10);
if (value < static_cast<int64_t>(INT32_MIN)) {
value = static_cast<int64_t>(INT32_MIN);
}
if (value > static_cast<int64_t>(INT32_MAX)) {
value = static_cast<int64_t>(INT32_MAX);
}
return static_cast<int32_t>(value);
}
template<::size64_t STRING_BUFFER_SIZE>
inline ::int64_t stoll(const apex::BaseString<STRING_BUFFER_SIZE> & str) noexcept
{
::int64_t value = ::strtoll(str.c_str(), nullptr, 10);
return value;
}
template<::size64_t STRING_BUFFER_SIZE>
inline ::uint32_t stoul(const apex::BaseString<STRING_BUFFER_SIZE> & str) noexcept
{
::uint64_t value = ::strtoul(str.c_str(), nullptr, 10);
if (value > static_cast<uint64_t>(UINT32_MAX)) {
value = static_cast<uint64_t>(UINT32_MAX);
}
return static_cast<uint32_t>(value & UINT32_MAX);
}
template<::size64_t STRING_BUFFER_SIZE>
inline ::uint64_t stoull(const apex::BaseString<STRING_BUFFER_SIZE> & str) noexcept
{
::uint64_t value = ::strtoull(str.c_str(), nullptr, 10);
return value;
}
} // namespace apex
// Extending std::hash for apex::BaseString<Buffer_Size>
// cppcheck-suppress syntaxError
namespace std
{
// hash combine function based on the boost implementation:
// https://www.boost.org/doc/libs/1_68_0/boost/container_hash/hash.hpp
template<size64_t SizeN>
struct hash<apex::BaseString<SizeN>>
{
size_t operator()(const apex::BaseString<SizeN> & str) const noexcept
{
size64_t seed = str.size();
for (size64_t idx = 0U; idx < str.size(); idx++) {
// cast char to unsigned char to size64_t for int array hashing
seed ^= static_cast<size64_t>(static_cast<uint8_t>(str[idx])) + 0x9e3779b9U +
(seed << 6U) + (seed >> 2U);
}
return seed;
}
};
} // namespace std
#endif // STRING__BASE_STRING_HPP_