/* * Frozen * Copyright 2016 QuarksLab * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 FROZEN_LETITGO_STRING_H #define FROZEN_LETITGO_STRING_H #include "frozen/bits/elsa.h" #include "frozen/bits/version.h" #include "frozen/bits/defines.h" #include #ifdef FROZEN_LETITGO_HAS_STRING_VIEW #include #endif namespace frozen { template class basic_string { using chr_t = _CharT; chr_t const *data_; std::size_t size_; public: template constexpr basic_string(chr_t const (&data)[N]) : data_(data), size_(N - 1) {} constexpr basic_string(chr_t const *data, std::size_t size) : data_(data), size_(size) {} #ifdef FROZEN_LETITGO_HAS_STRING_VIEW constexpr basic_string(std::basic_string_view data) : data_(data.data()), size_(data.size()) {} #endif constexpr basic_string(const basic_string &) noexcept = default; constexpr basic_string &operator=(const basic_string &) noexcept = default; constexpr std::size_t size() const { return size_; } constexpr chr_t operator[](std::size_t i) const { return data_[i]; } constexpr bool operator==(basic_string other) const { if (size_ != other.size_) return false; for (std::size_t i = 0; i < size_; ++i) if (data_[i] != other.data_[i]) return false; return true; } constexpr bool operator<(const basic_string &other) const { unsigned i = 0; while (i < size() && i < other.size()) { if ((*this)[i] < other[i]) { return true; } if ((*this)[i] > other[i]) { return false; } ++i; } return size() < other.size(); } constexpr const chr_t *data() const { return data_; } }; template struct elsa> { constexpr std::size_t operator()(basic_string<_CharT> value) const { std::size_t d = 5381; for (std::size_t i = 0; i < value.size(); ++i) d = d * 33 + static_cast(value[i]); return d; } // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function // With the lowest bits removed, based on experimental setup. constexpr std::size_t operator()(basic_string<_CharT> value, std::size_t seed) const { std::size_t d = (0x811c9dc5 ^ seed) * static_cast(0x01000193); for (std::size_t i = 0; i < value.size(); ++i) d = (d ^ static_cast(value[i])) * static_cast(0x01000193); return d >> 8 ; } }; using string = basic_string; using wstring = basic_string; using u16string = basic_string; using u32string = basic_string; #ifdef FROZEN_LETITGO_HAS_CHAR8T using u8string = basic_string; #endif namespace string_literals { constexpr string operator"" _s(const char *data, std::size_t size) { return {data, size}; } constexpr wstring operator"" _s(const wchar_t *data, std::size_t size) { return {data, size}; } constexpr u16string operator"" _s(const char16_t *data, std::size_t size) { return {data, size}; } constexpr u32string operator"" _s(const char32_t *data, std::size_t size) { return {data, size}; } #ifdef FROZEN_LETITGO_HAS_CHAR8T constexpr u8string operator"" _s(const char8_t *data, std::size_t size) { return {data, size}; } #endif } // namespace string_literals } // namespace frozen namespace std { template struct hash> { size_t operator()(frozen::basic_string<_CharT> s) const { return frozen::elsa>{}(s); } }; } // namespace std #endif