-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata.cpccKeyValueStr.h
More file actions
178 lines (134 loc) · 5.34 KB
/
data.cpccKeyValueStr.h
File metadata and controls
178 lines (134 loc) · 5.34 KB
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
174
175
176
177
178
/* *****************************************
* File: data.cpccKeyValueStr.h
* Purpose: Portable (cross-platform), light-weight library
* *****************************************
* Library: Cross Platform C++ Classes (cpcc)
* Copyright: 2020 StarMessage software.
* License: Free for opensource projects.
* Commercial license for closed source projects.
* Web: http://www.StarMessageSoftware.com/cpcclibrary
* https://github.com/starmessage/cpcc
* email: sales -at- starmessage.info
* *****************************************
*/
#pragma once
#include <string>
#include <map>
#include <algorithm>
#include "data.cpccWideCharSupport.h"
/**
A small and portable (cross platform) C++ class
Provides a std:map that can store any (primitive type) value
*/
// /////////////////////////////////////////////////////////////////////////////////////////////////
//
// class cpccKeyValueStr
//
// /////////////////////////////////////////////////////////////////////////////////////////////////
class cpccKeyValueStr
{
private:
typedef std::basic_string<TCHAR> tStringWN;
typedef std::map<tStringWN, tStringWN> tKeysAndValues;
protected:
tKeysAndValues m_map;
public:
typedef void (tEncodingFunc(tStringWN &));
// typedef struct { TCHAR *recordSeparator, bool addRecordSepararorEof, TCHAR *keyValueSeparator; } tSerializeConfig;
void removeKey(const TCHAR* aKey);
void clear(void);
const bool isEmpty(void) const { return m_map.empty(); }
const size_t getCount(void) const { return m_map.size(); }
const bool keyExists(const TCHAR* aKey) const;
const tStringWN get(const TCHAR* aKey) const;
void set(const TCHAR* aKey, const TCHAR* aValue);
void set(const TCHAR* aKey, const tStringWN &aValue) { set(aKey, aValue.c_str()); }
const tKeysAndValues &getMap(void) const { return m_map; }
const tStringWN serialize(const TCHAR* aRecordSeparator, const bool addRecordSeparatorToTheEnd, tEncodingFunc encodingFuncPtr) const;
bool isEqual(const cpccKeyValueStr & other) const;
void mergeFrom(const cpccKeyValueStr & other);
protected:
// called when set() functions are called.
// A descendant of this class can override this function to implement further actions,
// e.g. saving to a file
virtual void dataHasChanged(void) { }
};
// /////////////////////////////////////////////////////////////////////////////////////////////////
//
// class cpccKeyValue declaration
//
// /////////////////////////////////////////////////////////////////////////////////////////////////
inline void cpccKeyValueStr::mergeFrom(const cpccKeyValueStr & other)
{
m_map.insert(other.m_map.begin(), other.m_map.end());
}
inline bool cpccKeyValueStr::isEqual(const cpccKeyValueStr & other) const
{
// compare std::map
// https://stackoverflow.com/questions/8473009/how-to-efficiently-compare-two-maps-of-strings-in-c
if (m_map.size() != other.m_map.size())
return false;
return std::equal(m_map.begin(), m_map.end(), other.m_map.begin());
}
inline const cpccKeyValueStr::tStringWN cpccKeyValueStr::serialize(const TCHAR* aRecordSeparator, const bool addRecordSeparatorToTheEnd, tEncodingFunc encodingFuncPtr) const
{
tStringWN result;
const TCHAR *recordSeparator = _T("");
for (auto element : m_map)
{
tStringWN value(element.second);
if (encodingFuncPtr)
encodingFuncPtr(value);
result += recordSeparator + element.first + _T("=") + value;
if (aRecordSeparator)
recordSeparator = aRecordSeparator;
}
if (addRecordSeparatorToTheEnd)
result += recordSeparator;
return result;
}
inline void cpccKeyValueStr::removeKey(const TCHAR* aKey)
{
if (!aKey)
return;
m_map.erase(aKey);
dataHasChanged();
}
inline void cpccKeyValueStr::clear(void)
{
if (m_map.size() == 0)
return;
m_map.clear();
dataHasChanged();
}
inline const bool cpccKeyValueStr::keyExists(const TCHAR* aKey) const
{
if (!aKey)
return false;
return (m_map.find(aKey) != m_map.end());
}
inline void cpccKeyValueStr::set(const TCHAR* aKey, const TCHAR* aValue)
{
if (!aValue || !aKey) return;
// caching here
if (keyExists(aKey))
if (m_map[aKey].compare(aValue) == 0)
return; // the value is already there.
// set
m_map[aKey] = aValue;
dataHasChanged(); // let descendant classes know that the data has changes so they need to save it somewhere
}
inline const cpccKeyValueStr::tStringWN cpccKeyValueStr::get(const TCHAR* aKey) const
{
// amap[k]
// If k matches the key of an element in the container, the function returns a reference to its mapped value.
// If k does not match the key of any element in the container, the function inserts a new element with that key and returns a reference to its mapped value.
// this is not a const function:
if (aKey)
{
auto searchIterator = m_map.find(aKey);
if (searchIterator != m_map.end())
return searchIterator->second;
}
return _T("");
}