blob: 7b9f56311404d6a72e125404dd16798d419e410b (
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
|
/**
* Copyright (C) 2012 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mongo/db/field_ref.h"
#include "mongo/util/assert_util.h"
namespace mongo {
void FieldRef::parse(const StringData& dottedField) {
if (dottedField.size() == 0) {
return;
}
// We guarantee that accesses through getPart() will be valid while 'this' is. So we
// take a copy. We're going to be "chopping" up the copy into c-strings.
_fieldBase.reset(new char[dottedField.size()+1]);
dottedField.copyTo( _fieldBase.get(), true );
// Separate the field parts using '.' as a delimiter.
char* beg = _fieldBase.get();
char* cur = beg;
char* end = beg + dottedField.size();
while (true) {
if (cur != end && *cur != '.') {
cur++;
continue;
}
appendPart(StringData(beg, cur - beg));
if (cur != end) {
*cur = '\0';
beg = ++cur;
continue;
}
break;
}
}
void FieldRef::setPart(size_t i, const StringData& part) {
dassert(i < _size);
if (_replacements.size() != _size) {
_replacements.resize(_size);
}
_replacements[i] = part.toString();
if (i < kReserveAhead) {
_fixed[i] = _replacements[i];
}
else {
_variable[getIndex(i)] = _replacements[i];
}
}
size_t FieldRef::appendPart(const StringData& part) {
if (_size < kReserveAhead) {
_fixed[_size] = part;
}
else {
_variable.push_back(part);
}
return ++_size;
}
StringData FieldRef::getPart(size_t i) const {
dassert(i < _size);
if (i < kReserveAhead) {
return _fixed[i];
}
else {
return _variable[getIndex(i)];
}
}
void FieldRef::clear() {
_size = 0;
_variable.clear();
_fieldBase.reset();
_replacements.clear();
}
std::string FieldRef::dottedField() const {
std::string res;
if (_size == 0) {
return res;
}
res.append(_fixed[0].rawData(), _fixed[0].size());
for (size_t i=1; i<_size; i++) {
res.append(1, '.');
StringData part = getPart(i);
res.append(part.rawData(), part.size());
}
return res;
}
size_t FieldRef::numReplaced() const {
size_t res = 0;
for (size_t i = 0; i < _replacements.size(); i++) {
if (!_replacements[i].empty()) {
res++;
}
}
return res;
}
} // namespace mongo
|