1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2011-2016 Brazil
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License version 2.1 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#pragma once
20
21#include "dat.hpp"
22
23namespace grn {
24namespace dat {
25
26class GRN_DAT_API String {
27 public:
28 String()
29 : ptr_(NULL),
30 length_(0) {}
31 String(const void *ptr, UInt32 length)
32 : ptr_(static_cast<const UInt8 *>(ptr)),
33 length_(length) {}
34 template <UInt32 T>
35 explicit String(const char (&str)[T])
36 : ptr_(reinterpret_cast<const UInt8 *>(str)),
37 length_(T - 1) {}
38 String(const String &rhs)
39 : ptr_(rhs.ptr_),
40 length_(rhs.length_) {}
41
42 String &operator=(const String &rhs) {
43 set_ptr(rhs.ptr());
44 set_length(rhs.length());
45 return *this;
46 }
47
48 const UInt8 &operator[](UInt32 i) const {
49 GRN_DAT_DEBUG_THROW_IF(i >= length_);
50 return ptr_[i];
51 }
52
53 const void *ptr() const {
54 return ptr_;
55 }
56 UInt32 length() const {
57 return length_;
58 }
59
60 void set_ptr(const void *x) {
61 ptr_ = static_cast<const UInt8 *>(x);
62 }
63 void set_length(UInt32 x) {
64 length_ = x;
65 }
66
67 void assign(const void *ptr, UInt32 length) {
68 set_ptr(ptr);
69 set_length(length);
70 }
71
72 String substr(UInt32 offset = 0) const {
73 return String(ptr_ + offset, length_ - offset);
74 }
75 String substr(UInt32 offset, UInt32 length) const {
76 return String(ptr_ + offset, length);
77 }
78
79 // This function returns an integer as follows:
80 // - a negative value if *this < rhs,
81 // - zero if *this == rhs,
82 // - a positive value if *this > rhs,
83 // but if the offset is too large, the result is undefined.
84 int compare(const String &rhs, UInt32 offset = 0) const {
85 GRN_DAT_DEBUG_THROW_IF(offset > length());
86 GRN_DAT_DEBUG_THROW_IF(offset > rhs.length());
87
88 for (UInt32 i = offset; i < length(); ++i) {
89 if (i >= rhs.length()) {
90 return 1;
91 } else if ((*this)[i] != rhs[i]) {
92 return (*this)[i] - rhs[i];
93 }
94 }
95 return (length() == rhs.length()) ? 0 : -1;
96 }
97
98 bool starts_with(const String &str) const {
99 if (length() < str.length()) {
100 return false;
101 }
102 for (UInt32 i = 0; i < str.length(); ++i) {
103 if ((*this)[i] != str[i]) {
104 return false;
105 }
106 }
107 return true;
108 }
109
110 bool ends_with(const String &str) const {
111 if (length() < str.length()) {
112 return false;
113 }
114 UInt32 offset = length() - str.length();
115 for (UInt32 i = 0; i < str.length(); ++i) {
116 if ((*this)[offset + i] != str[i]) {
117 return false;
118 }
119 }
120 return true;
121 }
122
123 void swap(String *rhs) {
124 const UInt8 * const ptr_temp = ptr_;
125 ptr_ = rhs->ptr_;
126 rhs->ptr_ = ptr_temp;
127
128 const UInt32 length_temp = length_;
129 length_ = rhs->length_;
130 rhs->length_ = length_temp;
131 }
132
133 private:
134 const UInt8 *ptr_;
135 UInt32 length_;
136};
137
138inline bool operator==(const String &lhs, const String &rhs) {
139 if (lhs.length() != rhs.length()) {
140 return false;
141 } else if (lhs.ptr() == rhs.ptr()) {
142 return true;
143 }
144 for (UInt32 i = 0; i < lhs.length(); ++i) {
145 if (lhs[i] != rhs[i]) {
146 return false;
147 }
148 }
149 return true;
150}
151
152inline bool operator!=(const String &lhs, const String &rhs) {
153 return !(lhs == rhs);
154}
155
156inline bool operator<(const String &lhs, const String &rhs) {
157 return lhs.compare(rhs) < 0;
158}
159
160inline bool operator>(const String &lhs, const String &rhs) {
161 return rhs < lhs;
162}
163
164inline bool operator<=(const String &lhs, const String &rhs) {
165 return !(lhs > rhs);
166}
167
168inline bool operator>=(const String &lhs, const String &rhs) {
169 return !(lhs < rhs);
170}
171
172} // namespace dat
173} // namespace grn
174