diff options
author | Alberto Lerner <alerner@10gen.com> | 2013-01-16 10:36:40 -0500 |
---|---|---|
committer | Alberto Lerner <alerner@10gen.com> | 2013-01-16 10:36:40 -0500 |
commit | fd1bc4895b51dc65185ac5fa633bb0435860b936 (patch) | |
tree | f6594a3da5b2b975daced141c862544b98171def /src/mongo/db/field_ref.cpp | |
parent | 45772b7c149307803a3b0052b2468e2b254e19be (diff) | |
download | mongo-fd1bc4895b51dc65185ac5fa633bb0435860b936.tar.gz |
SERVER-5710 Changed KeyPattern.hasField() sematics to consider dotted field prefixes.
Diffstat (limited to 'src/mongo/db/field_ref.cpp')
-rw-r--r-- | src/mongo/db/field_ref.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/mongo/db/field_ref.cpp b/src/mongo/db/field_ref.cpp new file mode 100644 index 00000000000..7b9f5631140 --- /dev/null +++ b/src/mongo/db/field_ref.cpp @@ -0,0 +1,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 |