blob: d3823c3c608906b4814d4979e709aad76491cf7b [file] [log] [blame]
/*
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