| /* |
| 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 DATASTAX_INTERNAL_STRING_REF_HPP |
| #define DATASTAX_INTERNAL_STRING_REF_HPP |
| |
| #include "hash.hpp" |
| #include "macros.hpp" |
| #include "string.hpp" |
| #include "vector.hpp" |
| |
| #include <algorithm> |
| #include <assert.h> |
| #include <cctype> |
| #include <stddef.h> |
| #include <string.h> |
| |
| namespace datastax { |
| |
| template <class IsEqual> |
| int compare(const char* s1, const char* s2, size_t length, IsEqual is_equal) { |
| for (size_t i = 0; i < length; ++i) { |
| if (!is_equal(s1[i], s2[i])) { |
| return s1[i] < s2[i] ? -1 : 1; |
| } |
| } |
| return 0; |
| } |
| |
| class StringRef { |
| public: |
| typedef char value_type; |
| typedef const char* pointer; |
| typedef const char& reference; |
| typedef const char& const_reference; |
| typedef size_t size_type; |
| typedef ptrdiff_t difference_type; |
| typedef const char* const_iterator; |
| typedef const char* iterator; |
| |
| static const size_type npos; |
| |
| struct IsEqual { |
| bool operator()(char a, char b) const { return a == b; } |
| }; |
| |
| struct IsEqualInsensitive { |
| bool operator()(char a, char b) const { return std::toupper(a) == std::toupper(b); } |
| }; |
| |
| public: |
| StringRef() |
| : ptr_(NULL) |
| , length_(0) {} |
| |
| StringRef(const char* ptr, size_t length) |
| : ptr_(ptr) |
| , length_(length) {} |
| |
| StringRef(const char* str) |
| : ptr_(str) |
| , length_(SAFE_STRLEN(str)) {} |
| |
| StringRef(const String& str) |
| : ptr_(str.data()) |
| , length_(str.size()) {} |
| |
| const char* data() const { return ptr_; } |
| size_t size() const { return length_; } |
| size_t length() const { return length_; } |
| bool empty() const { return size() == 0; } |
| |
| iterator begin() const { return ptr_; } |
| iterator end() const { return ptr_ + length_; } |
| |
| char front() const { return ptr_[0]; } |
| char back() const { return ptr_[length_ - 1]; } |
| |
| String to_string() const { return String(ptr_, length_); } |
| |
| StringRef substr(size_t pos = 0, size_t length = npos) { |
| assert(pos < length_); |
| return StringRef(ptr_ + pos, std::min(length_ - pos, length)); |
| } |
| |
| size_t find(const StringRef& ref) const { |
| if (ref.length_ == 0) return 0; |
| if (length_ == 0) return npos; |
| const_iterator i = std::search(ptr_, ptr_ + length_, ref.ptr_, ref.ptr_ + ref.length_); |
| if (i == end()) return npos; |
| return i - begin(); |
| } |
| |
| int compare(const StringRef& ref) const { return compare(ref, IsEqual()); } |
| |
| int icompare(const StringRef& ref) const { return compare(ref, IsEqualInsensitive()); } |
| |
| bool equals(const StringRef& ref) const { return compare(ref) == 0; } |
| |
| bool iequals(const StringRef& ref) const { return icompare(ref) == 0; } |
| |
| bool operator==(const StringRef& ref) const { return equals(ref); } |
| |
| bool operator!=(const StringRef& ref) const { return !equals(ref); } |
| |
| bool operator<(const StringRef& ref) const { return compare(ref) < 0; } |
| |
| private: |
| template <class IsEqual> |
| int compare(const StringRef& ref, IsEqual is_equal) const { |
| if (length_ < ref.length_) { |
| return -1; |
| } else if (length_ > ref.length_) { |
| return 1; |
| } |
| return datastax::compare(ptr_, ref.ptr_, length_, is_equal); |
| } |
| |
| const char* ptr_; |
| size_t length_; |
| }; |
| |
| typedef internal::Vector<String> StringVec; |
| typedef internal::Vector<StringRef> StringRefVec; |
| |
| inline StringVec to_strings(const StringRefVec& refs) { |
| StringVec strings; |
| strings.reserve(refs.size()); |
| for (StringRefVec::const_iterator i = refs.begin(), end = refs.end(); i != end; ++i) { |
| strings.push_back(i->to_string()); |
| } |
| return strings; |
| } |
| |
| inline bool starts_with(const StringRef& input, const StringRef& target) { |
| return input.length() >= target.length() && |
| compare(input.data(), target.data(), target.size(), StringRef::IsEqual()) == 0; |
| } |
| |
| inline bool ends_with(const StringRef& input, const StringRef& target) { |
| return input.length() >= target.length() && |
| compare(input.data() + (input.length() - target.length()), target.data(), target.size(), |
| StringRef::IsEqual()) == 0; |
| } |
| |
| inline bool iequals(const StringRef& lhs, const StringRef& rhs) { return lhs.iequals(rhs); } |
| |
| struct StringRefIHash { |
| std::size_t operator()(const StringRef& s) const { |
| return hash::fnv1a(s.data(), s.size(), ::tolower); |
| } |
| }; |
| |
| struct StringRefIEquals { |
| bool operator()(const StringRef& lhs, const StringRef& rhs) const { return lhs.iequals(rhs); } |
| }; |
| |
| } // namespace datastax |
| |
| #endif |