The Pedigree Project  0.1
StaticCord.h
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef KERNEL_UTILITIES_STATICCORD_H
21 #define KERNEL_UTILITIES_STATICCORD_H
22 
26 #include "pedigree/kernel/compiler.h"
27 #include "pedigree/kernel/processor/types.h"
28 #include "pedigree/kernel/utilities/template.h" // IWYU pragma: keep
29 #include "pedigree/kernel/utilities/assert.h"
30 #include "pedigree/kernel/utilities/utility.h"
31 #include "pedigree/kernel/utilities/String.h"
32 
37 template <unsigned int N>
39 {
40  friend class CordIterator;
41  public:
43  {
44  friend class StaticCord;
45  public:
46  CordIterator(const StaticCord &owner) : cord(owner), segment(0), index(0)
47  {
48  }
49  virtual ~CordIterator() = default;
50 
52  {
53  ++index;
54  if (index >= cord.m_Segments[segment].length)
55  {
56  index = 0;
57  ++segment;
58  }
59 
60  if (segment > cord.m_NumSegments)
61  {
62  segment = cord.m_NumSegments;
63  index = 0;
64  }
65 
66  return *this;
67  }
68 
70  {
71  if (index)
72  {
73  --index;
74  }
75  else if (segment)
76  {
77  --segment;
78  index = cord.m_Segments[segment].length;
79  }
80 
81  return *this;
82  }
83 
84  char operator*() const
85  {
86  return cord.m_Segments[segment].ptr[index];
87  }
88 
89  bool operator==(const CordIterator &other) const
90  {
91  return segment == other.segment && index == other.index;
92  }
93 
94  bool operator!=(const CordIterator &other) const
95  {
96  return !(*this == other);
97  }
98 
99  protected:
100  CordIterator(const StaticCord &owner, bool end) : cord(owner), segment(0), index(0)
101  {
102  segment = owner.m_NumSegments;
103  }
104 
105  private:
106  const StaticCord &cord;
107  size_t segment;
108  size_t index;
109  };
110 
111  StaticCord() = default;
112  StaticCord(const StaticCord &other) : StaticCord()
113  {
114  assign(other);
115  }
116  virtual ~StaticCord() = default;
117 
118  StaticCord &operator=(const StaticCord &s)
119  {
120  assign(s);
121  return *this;
122  }
123 
124  void assign(const StaticCord &other)
125  {
126  m_Length = other.m_Length;
127  m_NumSegments = other.m_NumSegments;
128  pedigree_std::copy(m_Segments, other.m_Segments, N);
129  }
130 
131  void clear()
132  {
133  m_NumSegments = 0;
134  m_Length = 0;
135  }
136 
137  size_t length() const
138  {
139  return m_Length;
140  }
141 
142  char operator[](size_t index) const
143  {
144  size_t offset = 0;
145  for (size_t i = 0; i < m_NumSegments; ++i)
146  {
147  if ((index >= offset) && (index < (offset + m_Segments[i].length)))
148  {
149  return m_Segments[i].ptr[index - offset];
150  }
151 
152  offset += m_Segments[i].length;
153  }
154 
155  return 0;
156  }
157 
158  String toString() const
159  {
160  char *buf = new char[m_Length + 1];
161  size_t offset = 0;
162  for (size_t i = 0; i < m_NumSegments; ++i)
163  {
164  MemoryCopy(buf + offset, m_Segments[i].ptr, m_Segments[i].length);
165  offset += m_Segments[i].length;
166  }
167 
168  buf[m_Length] = 0;
169 
170  String result(buf, m_Length);
171  delete [] buf;
172  return result;
173  }
174 
175  void append(const char *s, size_t len=0)
176  {
177  assert(m_NumSegments < N);
178 
179  if (!len)
180  {
181  len = StringLength(s);
182  }
183 
184  m_Segments[m_NumSegments++] = CordSegment(s, len);
185  m_Length += len;
186  }
187 
188  CordIterator begin() const
189  {
190  return CordIterator(*this);
191  }
192 
193  CordIterator end() const
194  {
195  return CordIterator(*this, true);
196  }
197 
198  private:
199  struct CordSegment
200  {
201  CordSegment() = default;
202  CordSegment(const char *s, size_t len) : ptr(s), length(len) {}
203 
204  const char *ptr = nullptr;
205  size_t length = 0;
206  };
207 
208  CordSegment m_Segments[N];
209  size_t m_Length = 0;
210  size_t m_NumSegments = 0;
211 };
212 
213 // Specializations
214 extern template class EXPORTED_PUBLIC StaticCord<8>; // IWYU pragma: keep
215 
218 #endif // KERNEL_UTILITIES_STATICCORD_H
Definition: String.h:49
T operator++(T &x, int)
Global postincrement operator for types with overloaded preincrement operator.
Definition: template.h:41
#define assert(x)
Definition: assert.h:37
T operator--(T &x, int)
Global postdecrement operator for types with overloaded predecrement operator.
Definition: template.h:52
bool operator==(const Iterator< originalT, Struct, FunctionPrev, FunctionNext, T1 > &x1, const Iterator< originalT, Struct, FunctionPrev, FunctionNext, T2 > &x2)
Definition: Iterator.h:326
bool operator!=(const T1 &x1, const T2 &x2)
Global != operator for types with overloaded == operator.
Definition: template.h:32