blob: 08b74c4bfeff285c2ada61d55c6e5f3306a2ed4a (
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
|
/*
* minicargo - MRustC-specific clone of `cargo`
* - By John Hodge (Mutabah)
*
* stringlist.h
* - Helper classes for storing strings for use as cosnt char**
*
* StringList - Vector of strings
* StringListKV - Key/Value map
*/
#pragma once
#include <vector>
#include <string>
class StringList
{
::std::vector<::std::string> m_cached;
::std::vector<const char*> m_strings;
public:
StringList()
{
}
StringList(const StringList&) = delete;
StringList(StringList&&) = default;
const ::std::vector<const char*>& get_vec() const
{
return m_strings;
}
void push_back(::std::string s)
{
// If the cache list is about to move, update the pointers
if(m_cached.capacity() == m_cached.size())
{
// Make a bitmap of entries in `m_strings` that are pointers into `m_cached`
::std::vector<bool> b;
b.reserve(m_strings.size());
size_t j = 0;
for(const auto* s : m_strings)
{
if(j == m_cached.size())
break;
if(s == m_cached[j].c_str())
{
j ++;
b.push_back(true);
}
else
{
b.push_back(false);
}
}
// Add the new one
m_cached.push_back(::std::move(s));
// Update pointers
j = 0;
for(size_t i = 0; i < b.size(); i ++)
{
if(b[i])
{
m_strings[i] = m_cached.at(j++).c_str();
}
}
}
else
{
m_cached.push_back(::std::move(s));
}
m_strings.push_back(m_cached.back().c_str());
}
void push_back(const char* s)
{
m_strings.push_back(s);
}
};
class StringListKV: private StringList
{
StringList m_keys;
public:
StringListKV()
{
}
StringListKV(StringListKV&& x):
StringList(::std::move(x)),
m_keys(::std::move(x.m_keys))
{
}
void push_back(const char* k, ::std::string v)
{
m_keys.push_back(k);
StringList::push_back(v);
}
void push_back(const char* k, const char* v)
{
m_keys.push_back(k);
StringList::push_back(v);
}
void push_back(::std::string k, ::std::string v)
{
m_keys.push_back(k);
StringList::push_back(v);
}
void push_back(::std::string k, const char* v)
{
m_keys.push_back(k);
StringList::push_back(v);
}
struct Iter {
const StringListKV& v;
size_t i;
void operator++() {
this->i++;
}
::std::pair<const char*,const char*> operator*() {
return ::std::make_pair(this->v.m_keys.get_vec()[this->i], this->v.get_vec()[this->i]);
}
bool operator!=(const Iter& x) const {
return this->i != x.i;
}
};
Iter begin() const {
return Iter { *this, 0 };
}
Iter end() const {
return Iter { *this, m_keys.get_vec().size() };
}
friend ::std::ostream& operator<<(::std::ostream& os, const StringListKV& x) {
os << "{ ";
for(auto kv : x)
os << kv.first << "=" << kv.second << " ";
os << "}";
return os;
}
};
|