245 lines
5.9 KiB
C++
245 lines
5.9 KiB
C++
/*
|
|
* Copyright (C) 2019-2021 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cinttypes>
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
namespace NEO {
|
|
|
|
constexpr size_t constLength(const char *string) {
|
|
if (nullptr == string) {
|
|
return 0U;
|
|
}
|
|
auto it = string;
|
|
for (; *it != '\0'; ++it) {
|
|
}
|
|
return it - string;
|
|
}
|
|
|
|
class ConstStringRef {
|
|
public:
|
|
constexpr ConstStringRef() {
|
|
}
|
|
|
|
constexpr ConstStringRef(const ConstStringRef &rhs) : ptr(rhs.ptr), len(rhs.len) {
|
|
}
|
|
|
|
ConstStringRef &operator=(const ConstStringRef &rhs) {
|
|
this->ptr = rhs.ptr;
|
|
this->len = rhs.len;
|
|
return *this;
|
|
}
|
|
|
|
constexpr ConstStringRef(const char &c) noexcept
|
|
: ptr(&c), len(1) {
|
|
}
|
|
|
|
constexpr ConstStringRef(const char *const ptr) noexcept
|
|
: ptr(ptr), len(constLength(ptr)) {
|
|
}
|
|
|
|
constexpr ConstStringRef(const char *const ptr, const size_t length) noexcept
|
|
: ptr(ptr), len(length) {
|
|
}
|
|
|
|
template <size_t Length>
|
|
static constexpr ConstStringRef fromArray(const char (&array)[Length]) noexcept {
|
|
return ConstStringRef(array, Length);
|
|
}
|
|
|
|
ConstStringRef(const std::string &str) noexcept
|
|
: ptr(str.data()), len(str.length()) {
|
|
}
|
|
|
|
constexpr ConstStringRef substr(int offset, int len) const noexcept {
|
|
if (len >= 0) {
|
|
return ConstStringRef(this->ptr + offset, len);
|
|
} else {
|
|
return ConstStringRef(this->ptr + offset, this->len + len - offset);
|
|
}
|
|
}
|
|
|
|
constexpr ConstStringRef substr(int offset) const noexcept {
|
|
return ConstStringRef(this->ptr + offset, this->len - offset);
|
|
}
|
|
|
|
constexpr ConstStringRef truncated(int len) const noexcept {
|
|
if (len >= 0) {
|
|
return ConstStringRef(this->ptr, len);
|
|
} else {
|
|
return ConstStringRef(this->ptr, this->len + len);
|
|
}
|
|
}
|
|
|
|
constexpr const char *data() const noexcept {
|
|
return ptr;
|
|
}
|
|
|
|
constexpr char operator[](size_t pos) const noexcept {
|
|
return ptr[pos];
|
|
}
|
|
|
|
constexpr char operator[](int pos) const noexcept {
|
|
return ptr[pos];
|
|
}
|
|
|
|
explicit operator std::string() const {
|
|
return str();
|
|
}
|
|
|
|
std::string str() const {
|
|
return std::string(ptr, len);
|
|
}
|
|
|
|
constexpr size_t size() const noexcept {
|
|
return len;
|
|
}
|
|
|
|
constexpr size_t length() const noexcept {
|
|
return len;
|
|
}
|
|
|
|
constexpr bool empty() const noexcept {
|
|
return len == 0;
|
|
}
|
|
|
|
constexpr const char *begin() const noexcept {
|
|
return ptr;
|
|
}
|
|
|
|
constexpr const char *end() const noexcept {
|
|
return ptr + len;
|
|
}
|
|
|
|
constexpr bool contains(const char *subString) const noexcept {
|
|
const char *findBeg = ptr;
|
|
const char *findEnd = ptr + len;
|
|
while (findBeg != findEnd) {
|
|
const char *lhs = findBeg;
|
|
const char *rhs = subString;
|
|
while ((lhs < findEnd) && (*lhs == *rhs) && ('\0' != *rhs)) {
|
|
++lhs;
|
|
++rhs;
|
|
}
|
|
if ('\0' == *rhs) {
|
|
return true;
|
|
}
|
|
++findBeg;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
constexpr bool containsCaseInsensitive(const char *subString) const noexcept {
|
|
const char *findBeg = ptr;
|
|
const char *findEnd = ptr + len;
|
|
while (findBeg != findEnd) {
|
|
const char *lhs = findBeg;
|
|
const char *rhs = subString;
|
|
while ((lhs < findEnd) && (std::tolower(*lhs) == std::tolower(*rhs)) && ('\0' != *rhs)) {
|
|
++lhs;
|
|
++rhs;
|
|
}
|
|
if ('\0' == *rhs) {
|
|
return true;
|
|
}
|
|
++findBeg;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
constexpr bool startsWith(const char *subString) const noexcept {
|
|
const char *findEnd = ptr + len;
|
|
const char *lhs = ptr;
|
|
const char *rhs = subString;
|
|
while ((lhs < findEnd) && (*lhs == *rhs) && ('\0' != *rhs)) {
|
|
++lhs;
|
|
++rhs;
|
|
}
|
|
return ('\0' == *rhs);
|
|
}
|
|
|
|
protected:
|
|
ConstStringRef(std::nullptr_t) = delete;
|
|
|
|
const char *ptr = nullptr;
|
|
size_t len = 0U;
|
|
};
|
|
|
|
constexpr bool equals(const ConstStringRef &lhs, const ConstStringRef &rhs) {
|
|
if (lhs.size() != rhs.size()) {
|
|
return false;
|
|
}
|
|
|
|
for (size_t i = 0, e = lhs.size(); i < e; ++i) {
|
|
if (lhs[i] != rhs[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
constexpr bool equals(const ConstStringRef &lhs, const char *rhs) {
|
|
size_t i = 0;
|
|
for (size_t e = lhs.size(); i < e; ++i) {
|
|
if (lhs[i] != rhs[i]) {
|
|
return false;
|
|
}
|
|
if ((rhs[i] == '\0') && (i + 1 < e)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return (rhs[i] == '\0');
|
|
}
|
|
|
|
constexpr bool operator==(const ConstStringRef &lhs, const ConstStringRef &rhs) {
|
|
return equals(lhs, rhs);
|
|
}
|
|
|
|
constexpr bool operator==(const ConstStringRef &lhs, const char *rhs) {
|
|
return equals(lhs, rhs);
|
|
}
|
|
|
|
constexpr bool operator==(const char *lhs, const ConstStringRef &rhs) {
|
|
return equals(rhs, lhs);
|
|
}
|
|
|
|
constexpr bool operator!=(const ConstStringRef &lhs, const ConstStringRef &rhs) {
|
|
return false == equals(lhs, rhs);
|
|
}
|
|
|
|
constexpr bool operator!=(const ConstStringRef &lhs, const char *rhs) {
|
|
return false == equals(lhs, rhs);
|
|
}
|
|
|
|
constexpr bool operator!=(const char *lhs, const ConstStringRef &rhs) {
|
|
return false == equals(rhs, lhs);
|
|
}
|
|
|
|
constexpr bool equalsCaseInsensitive(const ConstStringRef &lhs, const ConstStringRef &rhs) {
|
|
if (lhs.size() != rhs.size()) {
|
|
return false;
|
|
}
|
|
|
|
constexpr auto caseDiff = 'a' - 'A';
|
|
for (size_t i = 0, e = lhs.size(); i < e; ++i) {
|
|
|
|
if ((lhs[i] != rhs[i]) & (lhs[i] + caseDiff != rhs[i]) & (lhs[i] != rhs[i] + caseDiff)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace NEO
|