The Pedigree Project 0.1
Cord.cc
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#include "pedigree/kernel/compiler.h"
21#include "pedigree/kernel/processor/types.h"
22#include "pedigree/kernel/utilities/Cord.h"
23#include "pedigree/kernel/utilities/List.h"
24#include "pedigree/kernel/utilities/String.h"
25
26Cord::Cord() = default;
27
28Cord::Cord(const Cord& other) : Cord() {
29 assign(other);
30}
31
32Cord::~Cord() {
33 clear();
34}
35
36Cord& Cord::operator=(const Cord& s) {
37 assign(s);
38 return *this;
39}
40
41void Cord::reserve(size_t segments) {
42 m_Segments.reserve(segments, true);
43}
44
45void Cord::assign(const Cord& other) {
46 if (this == &other)
47 return;
48
49 clear();
50
51 m_Segments.reserve(other.m_Segments.count(), false);
52
53 for (auto& it : other.m_Segments) {
54 m_Segments.pushBack(it);
55 m_Length += it.length;
56 }
57}
58
59void Cord::clear() {
60 m_Segments.clear(false);
61 m_Length = 0;
62}
63
64size_t Cord::length() const {
65 return m_Length;
66}
67
68String Cord::toString() const {
69 char* buf = new char[m_Length + 1];
70 size_t offset = 0;
71 for (auto& it : m_Segments) {
72 MemoryCopy(buf + offset, it.ptr, it.length);
73 offset += it.length;
74 }
75
76 buf[m_Length] = 0;
77
78 String result(buf, m_Length);
79 delete[] buf;
80 return result;
81}
82
83char Cord::operator[](size_t index) const {
84 size_t i = 0;
85 for (auto& it : m_Segments) {
86 if ((index >= i) && (index < (i + it.length))) {
87 return it.ptr[index - i];
88 }
89
90 i += it.length;
91 }
92
94 return 0;
95}
96
97void Cord::append(const char* s, size_t len) {
98 if (!len) {
99 len = StringLength(s);
100 }
101
102 if (!len)
103 return;
104
105 m_Segments.pushBack(CordSegment(s, len));
106 m_Length += len;
107}
108
109void Cord::prepend(const char* s, size_t len) {
110 if (!len) {
111 len = StringLength(s);
112 }
113
114 if (!len)
115 return;
116
117 m_Segments.pushFront(CordSegment(s, len));
118 m_Length += len;
119}
120
121void Cord::append(const String& str) {
122 append(str.cstr(), str.length());
123}
124
125void Cord::prepend(const String& str) {
126 prepend(str.cstr(), str.length());
127}
128
129Cord::CordIterator Cord::begin() const {
130 return Cord::CordIterator(*this);
131}
132
133Cord::CordIterator Cord::end() const {
134 return Cord::CordIterator(*this, true);
135}
136
137Cord::CordSegmentIterator Cord::segbegin() const {
138 return Cord::CordSegmentIterator(*this);
139}
140
141Cord::CordSegmentIterator Cord::segend() const {
142 return Cord::CordSegmentIterator(*this, true);
143}
144
145Cord::CordIterator::CordIterator(const Cord& owner) : cord(owner), segment(0), index(0) {
146 segptr = cord.m_Segments.count() ? &cord.m_Segments[segment] : nullptr;
147}
148
149Cord::CordIterator::CordIterator(const Cord& owner, bool end) : cord(owner), segment(0), index(0) {
150 segment = owner.m_Segments.count();
151 segptr = nullptr;
152}
153
154Cord::CordIterator::~CordIterator() = default;
155
156Cord::CordIterator& Cord::CordIterator::operator++() {
157 if (!segptr)
158 return *this;
159
160 ++index;
161 if (index >= segptr->length) {
162 index = 0;
163 ++segment;
164
165 segptr = segment < cord.m_Segments.count() ? &cord.m_Segments[segment] : nullptr;
166 }
167
168 return *this;
169}
170
171Cord::CordIterator& Cord::CordIterator::operator--() {
172 if (index) {
173 --index;
174 } else if (segment) {
175 --segment;
176 segptr = &cord.m_Segments[segment];
177 index = segptr->length - 1;
178 }
179
180 return *this;
181}
182
183char Cord::CordIterator::operator*() const {
184 return segptr->ptr[index];
185}
186
187bool Cord::CordIterator::operator==(const CordIterator& other) const {
188 return segment == other.segment && index == other.index;
189}
190
191bool Cord::CordIterator::operator!=(const CordIterator& other) const {
192 return !(*this == other);
193}
194
195Cord::CordSegmentIterator::CordSegmentIterator(const Cord& owner) : cord(owner), segment(0) {}
196
197Cord::CordSegmentIterator::CordSegmentIterator(const Cord& owner, bool end)
198 : cord(owner), segment(0) {
199 segment = owner.m_Segments.count();
200}
201
202Cord::CordSegmentIterator::~CordSegmentIterator() = default;
203
204Cord::CordSegmentIterator& Cord::CordSegmentIterator::operator++() {
205 ++segment;
206
207 if (segment > cord.m_Segments.count()) {
208 segment = cord.m_Segments.count();
209 }
210
211 return *this;
212}
213
214Cord::CordSegmentIterator& Cord::CordSegmentIterator::operator--() {
215 if (segment) {
216 --segment;
217 }
218
219 return *this;
220}
221
222const char* Cord::CordSegmentIterator::ptr() const {
223 return cord.m_Segments[segment].ptr;
224}
225
226size_t Cord::CordSegmentIterator::length() const {
227 return cord.m_Segments[segment].length;
228}
229
230bool Cord::CordSegmentIterator::operator==(const CordSegmentIterator& other) const {
231 return segment == other.segment;
232}
233
234bool Cord::CordSegmentIterator::operator!=(const CordSegmentIterator& other) const {
235 return !(*this == other);
236}
Definition Cord.h:33
char operator[](size_t index) const
Definition Cord.cc:83
void reserve(size_t segments)
Definition Cord.cc:41