Program Listing for File string_strict.hpp

Return to documentation for file (/tmp/ws/src/apex_containers/apex_containers/include/string/string_strict.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__STRING_STRICT_HPP_
#define STRING__STRING_STRICT_HPP_

#include <apexutils/apexdef.h>
#include <apexutils/apex_string.h>
#include <apex_containers/visibility_control.hpp>

#include <stdexcept>
#include <cstring>
#include <algorithm>
#include <istream>
#include <ostream>
#include <string>

namespace apex
{

template<::size64_t STRING_BUFFER_SIZE>
class StringStrict : public BaseString<STRING_BUFFER_SIZE>
{
public:
  using iterator =
    typename apex::template BaseString<STRING_BUFFER_SIZE>::template abs_iterator<::char8_t>;
  using const_iterator = typename
    apex::template BaseString<STRING_BUFFER_SIZE>::template abs_iterator<const ::char8_t>;

  StringStrict(void)
  : apex::BaseString<STRING_BUFFER_SIZE>()
  {
  }

  StringStrict(const ::size64_t n, const ::char8_t c)
  : StringStrict()
  {
    if ((n != StringStrict::npos) && (n > this->capacity())) {
      throw std::overflow_error("n > this->capacity()");
    }
    const ::size64_t chars_to_fill = (n < this->capacity()) ? n : this->capacity();
    // Ignore unneeded returned pointer to destination
    (void)memset(this->m_string, c, chars_to_fill);
  }

  StringStrict<STRING_BUFFER_SIZE> & operator+=(const ::char8_t * const src)
  {
    if (src != nullptr) {
      const ::size64_t my_length = this->length();
      const ::size64_t their_length = ::strnlen(src, this->get_buffer_size());
      if ((my_length + their_length + 1U) <= this->get_buffer_size()) {
        // Ignore returned self reference
        (void)::memmove(&(this->m_string[0U]) + my_length, src, their_length);
        this->m_string[my_length + their_length] = '\0';
      } else {
        throw std::overflow_error("Can't add too large string");
      }
    } else {
      throw std::invalid_argument("Can't add NULL string");
    }
    return *this;
  }

  StringStrict<STRING_BUFFER_SIZE> & operator+=(const ::char8_t chr)
  {
    const ::size64_t my_length = this->length();
    if ((my_length + 2U) <= this->get_buffer_size()) {
      this->m_string[my_length] = chr;
      this->m_string[my_length + 1U] = '\0';
    } else {
      throw std::overflow_error("Can't add too large string");
    }
    return *this;
  }

  StringStrict(const ::char8_t * const str)  // NOLINT: constructors should be explicit, but
  : StringStrict()  // we want to have ability to convert a classic char pointer to apex::string
  {
    *this += str;
  }

  explicit StringStrict(const ::apex_string_t & str)
  : StringStrict(str.c_str)
  {
  }

  template<::size64_t LEN>
  StringStrict(const apex::BaseString<LEN> & src)  // NOLINT: constructors should be explicit, but
  : StringStrict(src.c_str())  // we want to have ability to assign another string
  {
  }

  explicit StringStrict(const BaseString<STRING_BUFFER_SIZE> & src)
  : StringStrict(src.c_str())
  {
  }

  // Addition

  template<::size64_t LEN>
  const StringStrict<STRING_BUFFER_SIZE + LEN> operator+(const StringStrict<LEN> & rhs) const
  {
    StringStrict<STRING_BUFFER_SIZE + LEN> retval(*this);
    retval += rhs.c_str();
    return retval;
  }

  template<::size64_t LEN>
  auto
  operator+(const char (& rhs)[LEN]) const noexcept
  {
    apex::StringStrict<STRING_BUFFER_SIZE + LEN> retval(*this);
    retval += rhs;
    return retval;
  }

  const apex::StringStrict<STRING_BUFFER_SIZE + APEX_STRING_SIZE>
  operator+(const ::apex_string_t & rhs) const
  {
    StringStrict<STRING_BUFFER_SIZE + APEX_STRING_SIZE> retval(*this);
    retval += rhs.c_str;
    return retval;
  }

  // Increments

  template<::size64_t LEN>
  StringStrict & operator+=(const StringStrict<LEN> & rhs)
  {
    *this += rhs.c_str();
    return *this;
  }

  StringStrict<STRING_BUFFER_SIZE> & operator+=(const apex_string_t & src)
  {
    *this += src.c_str;
    return *this;
  }

  // Assignments

  StringStrict<STRING_BUFFER_SIZE> & operator=(const BaseString<STRING_BUFFER_SIZE> & rhs)
  {
    // Ignore unneeded pointer to destination
    (void)::memset(&(this->m_string[0U]), 0, this->get_buffer_size());
    *this += rhs.c_str();
    return *this;
  }

  template<::size64_t LEN>
  StringStrict<STRING_BUFFER_SIZE> & operator=(const BaseString<LEN> & rhs)
  {
    // Ignore unneeded pointer to destination
    (void)::memset(&(this->m_string[0U]), 0, this->get_buffer_size());
    *this += rhs.c_str();
    return *this;
  }

  StringStrict<STRING_BUFFER_SIZE> & operator=(const char8_t * const src)
  {
    // Ignore unneeded pointer to destination
    (void)::memset(&(this->m_string[0U]), 0, this->get_buffer_size());
    *this += src;
    return *this;
  }

  StringStrict<STRING_BUFFER_SIZE> & operator=(const apex_string_t & src)
  {
    // Ignore unneeded pointer to destination
    (void)::memset(&(this->m_string[0U]), 0, this->get_buffer_size());
    *this += src.c_str;
    return *this;
  }

  static apex::StringStrict<STRING_BUFFER_SIZE> to_string(const uint32_t value);

  iterator begin() noexcept
  {
    return iterator(&(BaseString<STRING_BUFFER_SIZE>::m_string[0U]));
  }

  iterator end() noexcept
  {
    return iterator(
      &(BaseString<STRING_BUFFER_SIZE>::m_string[0U]) + BaseString<STRING_BUFFER_SIZE>::size());
  }

  const_iterator cbegin() const noexcept
  {
    return const_iterator(&(BaseString<STRING_BUFFER_SIZE>::m_string[0U]));
  }

  const_iterator cend() const noexcept
  {
    return const_iterator(
      &(BaseString<STRING_BUFFER_SIZE>::m_string[0U]) +
      BaseString<STRING_BUFFER_SIZE>::size());
  }
};

template<::size64_t LEN>
inline apex::StringStrict<APEX_STRING_SIZE + LEN>
operator+(const ::apex_string_t & lhs, const apex::StringStrict<LEN> & rhs)
{
  StringStrict<APEX_STRING_SIZE + LEN> retval(lhs.c_str);
  retval += rhs.c_str();
  return retval;
}

template<::size64_t CSTR_LEN, ::size64_t APEX_STRING_LEN>
inline auto
operator+(const char (& lhs)[CSTR_LEN], const apex::StringStrict<APEX_STRING_LEN> & rhs)
{
  StringStrict<CSTR_LEN + APEX_STRING_LEN> retval(lhs);
  retval += rhs;
  return retval;
}


using string_strict8_t = StringStrict<8U>;
static_assert(sizeof(string_strict8_t) == 8U, "sizeof(string_strict8_t) != 8U");

using string_strict16_t = StringStrict<16U>;
static_assert(sizeof(string_strict16_t) == 16U, "sizeof(string_strict16_t) != 16U");

using string_strict32_t = StringStrict<32U>;
static_assert(sizeof(string_strict32_t) == 32U, "sizeof(string_strict32_t) != 32U");

using string_strict64_t = StringStrict<64U>;
static_assert(sizeof(string_strict64_t) == 64U, "sizeof(string_strict64_t) != 64U");

using string_strict128_t = StringStrict<128U>;
static_assert(sizeof(string_strict128_t) == 128U, "sizeof(string_strict8_t) != 128U");

using string_strict256_t = StringStrict<APEX_STRING_SIZE>;
static_assert(sizeof(string_strict256_t) == 256U, "sizeof(string_strict256_t) != 256U");

template<size64_t STRING_BUFFER_SIZE>
typename ::std::istream & operator>>(
  std::istream & in_stream,
  apex::StringStrict<STRING_BUFFER_SIZE> & str)
{
  typename apex::StringStrict<STRING_BUFFER_SIZE>::iterator it = str.begin();
  return in_stream.getline(&(it[0U]), str.get_buffer_size());
}

}  // namespace apex

namespace std
{
template<size64_t SizeN>
struct hash<apex::StringStrict<SizeN>>: std::hash<apex::BaseString<SizeN>> {};
}  // namespace std

#endif  // STRING__STRING_STRICT_HPP_