// The MIT License (MIT) // // Copyright (c) 2018 Mateusz Pusz // // 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. #pragma once #include #include namespace units { template struct basic_fixed_string { CharT data_[N + 1] = {}; constexpr basic_fixed_string(CharT ch) noexcept { data_[0] = ch; } constexpr basic_fixed_string(const CharT (&txt)[N + 1]) noexcept { for(std::size_t i = 0; i < N; ++i) data_[i] = txt[i]; } [[nodiscard]] constexpr std::size_t size() const noexcept { return N; } [[nodiscard]] constexpr const CharT* c_str() const noexcept { return data_; } [[nodiscard]] constexpr const CharT& operator[](std::size_t index) const noexcept { return data_[index]; } [[nodiscard]] constexpr CharT operator[](std::size_t index) noexcept { return data_[index]; } // auto operator==(const basic_fixed_string &) = default; [[nodiscard]] constexpr friend bool operator==(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept { for(size_t i = 0; i != lhs.size(); ++i) if(lhs.data_[i] != rhs.data_[i]) return false; return true; } template [[nodiscard]] constexpr friend bool operator==(const basic_fixed_string&, const basic_fixed_string&) noexcept { return false; } template [[nodiscard]] constexpr friend bool operator<(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept { using std::begin, std::end; auto first1 = begin(lhs.data_); auto first2 = begin(rhs.data_); const auto last1 = std::prev(end(lhs.data_)); // do not waste time for '\0' const auto last2 = std::prev(end(rhs.data_)); for(; (first1 != last1) && (first2 != last2); ++first1, (void)++first2 ) { if(*first1 < *first2) return true; if(*first2 < *first1) return false; } return first1 == last1 && first2 != last2; } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const basic_fixed_string& txt) { return os << txt.c_str(); } template [[nodiscard]] constexpr friend basic_fixed_string operator+(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept { CharT txt[N + N2 + 1] = {}; for(size_t i = 0; i != N; ++i) txt[i] = lhs[i]; for(size_t i = 0; i != N2; ++i) txt[N + i] = rhs[i]; return units::basic_fixed_string(txt); } }; template basic_fixed_string(const CharT (&str)[N]) -> basic_fixed_string; template basic_fixed_string(CharT) -> basic_fixed_string; template using fixed_string = basic_fixed_string; }