-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdyn_string_lib.cc
169 lines (152 loc) · 4.73 KB
/
dyn_string_lib.cc
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
#include <cstring>
#include "dyn_string.hh"
using namespace std;
namespace dyn_string {
DynString::DynString(char *p) : len_(strlen(p)), s_(new char[strlen(p) + 1]) {
/*
The strncpy() function is similar, except that at most n bytes of src
are copied. Warning: If there is no null byte among the first n bytes
of src, the string placed in dest will not be null-terminated.
*/
strncpy(s_.get(), p, len_ + 1u);
assert(len_ == strlen(s_.get()));
}
DynString::DynString(const char *p)
: len_(strlen(p)), s_(new char[strlen(p) + 1]) {
strncpy(s_.get(), p, strlen(p) + 1u);
assert(len_ == strlen(s_.get()));
}
DynString &DynString::operator=(const DynString &str) {
if (&str != this) {
this->s_ = make_unique<char[]>(str.len_ + 1u);
strncpy(this->s_.get(), str.s_.get(), str.len_ + 1u);
this->len_ = str.len_;
}
return *this;
}
void DynString::concat(const DynString &a, const DynString &b) {
if (0u == b.len_) {
*this = a;
return;
}
if (0u == a.len_) {
*this = b;
return;
}
this->len_ = a.len_ + b.len_;
this->s_ = make_unique<char[]>(this->len_ + 1u);
// The strncpy() function is similar, except that at most n bytes of
// src are copied. Warning: If there is no null byte among the
// first n bytes of src, the string placed in dest will not be
// null-terminated.
strncpy(this->s_.get(), a.contents(), a.len_ + 1u);
// temp is null-terminated.
assert(a.len_ == strlen(this->s_.get()));
// The strcat() function appends the src string to the dest string,
// overwriting the terminating null byte ('\0') at the end of dest,
// and then adds a terminating null byte. If src contains n or more
// bytes, strncat() writes n+1 bytes to dest (n from src plus the
// terminating null byte). Therefore, the size of dest must be at
// least strlen(dest)+n+1.
strncat(this->s_.get(), b.contents(), b.len_);
assert(this->len_ == strlen(this->s_.get()));
}
int DynString::compare(const DynString &a) const {
unsigned i = 0u;
while ((a.s_.get()[i] == contents()[i]) && (a.s_.get()[i] != '\0')) {
i++;
}
// Got to the end of both strings, and all chars matched.
if ((len_ == i) && (a.len_ == len_)) {
return 0;
}
// Evaluates to true if a.s_ is NULL. Makes sense since NUL is ASCII 0x0.
if (contents()[i] > a.s_.get()[i]) {
return 1;
}
// (contents()[i] < a.s_[i])
return -1;
}
void DynString::reverse() {
if (0 == len_) {
return;
}
assert(len_ == strlen(s_.get()));
unsigned i = 0u;
while (i < len_ / 2u) {
char keep = s_.get()[i];
// Subtract 1 in order to skip the NULL on reversal.
s_.get()[i] = s_.get()[(len_ - 1u) - i];
s_.get()[(len_ - 1u) - i] = keep;
i++;
}
// Add it to the new end.
s_.get()[len_] = '\0';
assert(len_ == strlen(s_.get()));
}
void DynString::swap(DynString &str) {
if (str == *this) {
return;
}
DynString a(str.s_.get());
str = *this;
*this = a;
}
bool operator==(const DynString &a, const DynString &b) {
return (0 == strcmp(a.s_.get(), b.s_.get()));
}
// Cannot be a member function, as it acts on a list of objects, and is
// therefore not associated with a particular one.
// We don't have to pass in a function pointer, as compare() is a member
// function of the class of objects to which is applied.
void dyn_string_sort(DynString *dynstr, size_t cursor, size_t len) {
assert(dynstr != 0);
if (cursor < 2u) {
return;
}
// unsigned depth = len - cursor;
// cout << " depth: " << depth << endl;
// unsigned i = depth;
// while (i < len) {
// (dynstr+i)->print();
// i++;
// }
// cout << endl;
// Note that all these functions add and subtract 1 rather than incrementing
// or decrementing.
if (cursor > 2) {
// Work done on the way down to the end of the array.
if (dynstr->compare(*(dynstr + 1)) > 0) {
dynstr->swap(*(dynstr + 1));
}
// Descend to the bottom.
dyn_string_sort(dynstr + 1, cursor - 1, len);
}
// If upon return from previous sort, the array is
// disordered, descend again and fix until there's
// no more work.
// Work done on the way back up from the end of the array.
if (dynstr->compare(*(dynstr + 1)) > 0) {
dynstr->swap(*(dynstr + 1));
dyn_string_sort(dynstr + 1, cursor - 1, len);
}
return;
}
std::ostream &operator<<(std::ostream &out, const DynString &a) {
out << a.s_.get();
return out;
}
std::ostream &print_some(std::ostream &out, const DynString &a, size_t n = 0) {
if (!((0u == n) || a.empty())) {
size_t bound = (n <= a.len()) ? n : a.len();
size_t ctr = 0u;
while (ctr < bound) {
out << a.s_[ctr];
ctr++;
}
// Apparently std::ostringstream automagically adds the trailing null.
// out << '0';
}
return out;
}
} // namespace dyn_string