summaryrefslogtreecommitdiff
path: root/storage/mroonga/vendor/groonga/lib/dat/string.hpp
blob: aead21cac1804cdae96a767c5a1601b73788ca2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* -*- c-basic-offset: 2 -*- */
/*
  Copyright(C) 2011-2016 Brazil

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License version 2.1 as published by the Free Software Foundation.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA
*/

#pragma once

#include "dat.hpp"

namespace grn {
namespace dat {

class GRN_DAT_API String {
 public:
  String()
      : ptr_(NULL),
        length_(0) {}
  String(const void *ptr, UInt32 length)
      : ptr_(static_cast<const UInt8 *>(ptr)),
        length_(length) {}
  template <UInt32 T>
  explicit String(const char (&str)[T])
      : ptr_(reinterpret_cast<const UInt8 *>(str)),
        length_(T - 1) {}
  String(const String &rhs)
      : ptr_(rhs.ptr_),
        length_(rhs.length_) {}

  String &operator=(const String &rhs) {
    set_ptr(rhs.ptr());
    set_length(rhs.length());
    return *this;
  }

  const UInt8 &operator[](UInt32 i) const {
    GRN_DAT_DEBUG_THROW_IF(i >= length_);
    return ptr_[i];
  }

  const void *ptr() const {
    return ptr_;
  }
  UInt32 length() const {
    return length_;
  }

  void set_ptr(const void *x) {
    ptr_ = static_cast<const UInt8 *>(x);
  }
  void set_length(UInt32 x) {
    length_ = x;
  }

  void assign(const void *ptr, UInt32 length) {
    set_ptr(ptr);
    set_length(length);
  }

  String substr(UInt32 offset = 0) const {
    return String(ptr_ + offset, length_ - offset);
  }
  String substr(UInt32 offset, UInt32 length) const {
    return String(ptr_ + offset, length);
  }

  // This function returns an integer as follows:
  // - a negative value if *this < rhs,
  // - zero if *this == rhs,
  // - a positive value if *this > rhs,
  // but if the offset is too large, the result is undefined.
  int compare(const String &rhs, UInt32 offset = 0) const {
    GRN_DAT_DEBUG_THROW_IF(offset > length());
    GRN_DAT_DEBUG_THROW_IF(offset > rhs.length());

    for (UInt32 i = offset; i < length(); ++i) {
      if (i >= rhs.length()) {
        return 1;
      } else if ((*this)[i] != rhs[i]) {
        return (*this)[i] - rhs[i];
      }
    }
    return (length() == rhs.length()) ? 0 : -1;
  }

  bool starts_with(const String &str) const {
    if (length() < str.length()) {
      return false;
    }
    for (UInt32 i = 0; i < str.length(); ++i) {
      if ((*this)[i] != str[i]) {
        return false;
      }
    }
    return true;
  }

  bool ends_with(const String &str) const {
    if (length() < str.length()) {
      return false;
    }
    UInt32 offset = length() - str.length();
    for (UInt32 i = 0; i < str.length(); ++i) {
      if ((*this)[offset + i] != str[i]) {
        return false;
      }
    }
    return true;
  }

  void swap(String *rhs) {
    const UInt8 * const ptr_temp = ptr_;
    ptr_ = rhs->ptr_;
    rhs->ptr_ = ptr_temp;

    const UInt32 length_temp = length_;
    length_ = rhs->length_;
    rhs->length_ = length_temp;
  }

 private:
  const UInt8 *ptr_;
  UInt32 length_;
};

inline bool operator==(const String &lhs, const String &rhs) {
  if (lhs.length() != rhs.length()) {
    return false;
  } else if (lhs.ptr() == rhs.ptr()) {
    return true;
  }
  for (UInt32 i = 0; i < lhs.length(); ++i) {
    if (lhs[i] != rhs[i]) {
      return false;
    }
  }
  return true;
}

inline bool operator!=(const String &lhs, const String &rhs) {
  return !(lhs == rhs);
}

inline bool operator<(const String &lhs, const String &rhs) {
  return lhs.compare(rhs) < 0;
}

inline bool operator>(const String &lhs, const String &rhs) {
  return rhs < lhs;
}

inline bool operator<=(const String &lhs, const String &rhs) {
  return !(lhs > rhs);
}

inline bool operator>=(const String &lhs, const String &rhs) {
  return !(lhs < rhs);
}

}  // namespace dat
}  // namespace grn