summaryrefslogtreecommitdiff
path: root/src/mongo/db/field_ref.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/field_ref.cpp')
-rw-r--r--src/mongo/db/field_ref.cpp394
1 files changed, 194 insertions, 200 deletions
diff --git a/src/mongo/db/field_ref.cpp b/src/mongo/db/field_ref.cpp
index 9881e42b75a..e3bc5305c0b 100644
--- a/src/mongo/db/field_ref.cpp
+++ b/src/mongo/db/field_ref.cpp
@@ -28,262 +28,256 @@
#include "mongo/db/field_ref.h"
-#include <algorithm> // for min
+#include <algorithm> // for min
#include "mongo/util/assert_util.h"
namespace mongo {
- FieldRef::FieldRef() : _size(0) {}
+FieldRef::FieldRef() : _size(0) {}
- FieldRef::FieldRef(StringData path) : _size(0) {
- parse(path);
- }
-
- void FieldRef::parse(StringData path) {
- if (path.size() == 0) {
- return;
- }
+FieldRef::FieldRef(StringData path) : _size(0) {
+ parse(path);
+}
- if (_size != 0) {
- clear();
- }
-
- // We guarantee that accesses through getPart() will be valid while 'this' is. So we
- // keep a copy in a local sting.
-
- _dotted = path.toString();
-
- // Separate the field parts using '.' as a delimiter.
- std::string::iterator beg = _dotted.begin();
- std::string::iterator cur = beg;
- const std::string::iterator end = _dotted.end();
- while (true) {
- if (cur != end && *cur != '.') {
- cur++;
- continue;
- }
-
- // If cur != beg then we advanced cur in the loop above, so we have a real sequence
- // of characters to add as a new part. Otherwise, we may be parsing something odd,
- // like "..", and we need to add an empty StringData piece to represent the "part"
- // in-between the dots. This also handles the case where 'beg' and 'cur' are both
- // at 'end', which can happen if we are parsing anything with a terminal "."
- // character. In that case, we still need to add an empty part, but we will break
- // out of the loop below since we will not execute the guarded 'continue' and will
- // instead reach the break statement.
-
- if (cur != beg)
- appendPart(StringData(&*beg, cur - beg));
- else
- appendPart(StringData());
-
- if (cur != end) {
- beg = ++cur;
- continue;
- }
+void FieldRef::parse(StringData path) {
+ if (path.size() == 0) {
+ return;
+ }
- break;
- }
+ if (_size != 0) {
+ clear();
}
- void FieldRef::setPart(size_t i, StringData part) {
- dassert(i < _size);
+ // We guarantee that accesses through getPart() will be valid while 'this' is. So we
+ // keep a copy in a local sting.
- if (_replacements.size() != _size) {
- _replacements.resize(_size);
- }
+ _dotted = path.toString();
- _replacements[i] = part.toString();
- if (i < kReserveAhead) {
- _fixed[i] = _replacements[i];
+ // Separate the field parts using '.' as a delimiter.
+ std::string::iterator beg = _dotted.begin();
+ std::string::iterator cur = beg;
+ const std::string::iterator end = _dotted.end();
+ while (true) {
+ if (cur != end && *cur != '.') {
+ cur++;
+ continue;
}
- else {
- _variable[getIndex(i)] = _replacements[i];
- }
- }
- size_t FieldRef::appendPart(StringData part) {
- if (_size < kReserveAhead) {
- _fixed[_size] = part;
- }
- else {
- _variable.push_back(part);
+ // If cur != beg then we advanced cur in the loop above, so we have a real sequence
+ // of characters to add as a new part. Otherwise, we may be parsing something odd,
+ // like "..", and we need to add an empty StringData piece to represent the "part"
+ // in-between the dots. This also handles the case where 'beg' and 'cur' are both
+ // at 'end', which can happen if we are parsing anything with a terminal "."
+ // character. In that case, we still need to add an empty part, but we will break
+ // out of the loop below since we will not execute the guarded 'continue' and will
+ // instead reach the break statement.
+
+ if (cur != beg)
+ appendPart(StringData(&*beg, cur - beg));
+ else
+ appendPart(StringData());
+
+ if (cur != end) {
+ beg = ++cur;
+ continue;
}
- return ++_size;
+
+ break;
}
+}
- void FieldRef::reserialize() const {
- std::string nextDotted;
- // Reserve some space in the string. We know we will have, at minimum, a character for
- // each component we are writing, and a dot for each component, less one. We don't want
- // to reserve more, since we don't want to forfeit the SSO if it is applicable.
- nextDotted.reserve((_size * 2) - 1);
-
- // Concatenate the fields to a new string
- for (size_t i = 0; i != _size; ++i) {
- if (i > 0)
- nextDotted.append(1, '.');
- const StringData part = getPart(i);
- nextDotted.append(part.rawData(), part.size());
- }
+void FieldRef::setPart(size_t i, StringData part) {
+ dassert(i < _size);
- // Make the new string our contents
- _dotted.swap(nextDotted);
-
- // Fixup the parts to refer to the new string
- std::string::const_iterator where = _dotted.begin();
- const std::string::const_iterator end = _dotted.end();
- for (size_t i = 0; i != _size; ++i) {
- StringData& part = (i < kReserveAhead) ? _fixed[i] : _variable[getIndex(i)];
- const size_t size = part.size();
- part = StringData(&*where, size);
- where += size;
- // skip over '.' unless we are at the end.
- if (where != end) {
- dassert(*where == '.');
- ++where;
- }
- }
+ if (_replacements.size() != _size) {
+ _replacements.resize(_size);
+ }
- // Drop any replacements
- _replacements.clear();
+ _replacements[i] = part.toString();
+ if (i < kReserveAhead) {
+ _fixed[i] = _replacements[i];
+ } else {
+ _variable[getIndex(i)] = _replacements[i];
}
+}
- StringData FieldRef::getPart(size_t i) const {
- dassert(i < _size);
+size_t FieldRef::appendPart(StringData part) {
+ if (_size < kReserveAhead) {
+ _fixed[_size] = part;
+ } else {
+ _variable.push_back(part);
+ }
+ return ++_size;
+}
+
+void FieldRef::reserialize() const {
+ std::string nextDotted;
+ // Reserve some space in the string. We know we will have, at minimum, a character for
+ // each component we are writing, and a dot for each component, less one. We don't want
+ // to reserve more, since we don't want to forfeit the SSO if it is applicable.
+ nextDotted.reserve((_size * 2) - 1);
+
+ // Concatenate the fields to a new string
+ for (size_t i = 0; i != _size; ++i) {
+ if (i > 0)
+ nextDotted.append(1, '.');
+ const StringData part = getPart(i);
+ nextDotted.append(part.rawData(), part.size());
+ }
- if (i < kReserveAhead) {
- return _fixed[i];
- }
- else {
- return _variable[getIndex(i)];
+ // Make the new string our contents
+ _dotted.swap(nextDotted);
+
+ // Fixup the parts to refer to the new string
+ std::string::const_iterator where = _dotted.begin();
+ const std::string::const_iterator end = _dotted.end();
+ for (size_t i = 0; i != _size; ++i) {
+ StringData& part = (i < kReserveAhead) ? _fixed[i] : _variable[getIndex(i)];
+ const size_t size = part.size();
+ part = StringData(&*where, size);
+ where += size;
+ // skip over '.' unless we are at the end.
+ if (where != end) {
+ dassert(*where == '.');
+ ++where;
}
}
- bool FieldRef::isPrefixOf( const FieldRef& other ) const {
- // Can't be a prefix if the size is equal to or larger.
- if ( _size >= other._size ) {
- return false;
- }
+ // Drop any replacements
+ _replacements.clear();
+}
- // Empty FieldRef is not a prefix of anything.
- if ( _size == 0 ) {
- return false;
- }
+StringData FieldRef::getPart(size_t i) const {
+ dassert(i < _size);
- size_t common = commonPrefixSize( other );
- return common == _size && other._size > common;
+ if (i < kReserveAhead) {
+ return _fixed[i];
+ } else {
+ return _variable[getIndex(i)];
}
+}
- size_t FieldRef::commonPrefixSize( const FieldRef& other ) const {
- if (_size == 0 || other._size == 0) {
- return 0;
- }
+bool FieldRef::isPrefixOf(const FieldRef& other) const {
+ // Can't be a prefix if the size is equal to or larger.
+ if (_size >= other._size) {
+ return false;
+ }
- size_t maxPrefixSize = std::min( _size-1, other._size-1 );
- size_t prefixSize = 0;
+ // Empty FieldRef is not a prefix of anything.
+ if (_size == 0) {
+ return false;
+ }
- while ( prefixSize <= maxPrefixSize ) {
- if ( getPart( prefixSize ) != other.getPart( prefixSize ) ) {
- break;
- }
- prefixSize++;
- }
+ size_t common = commonPrefixSize(other);
+ return common == _size && other._size > common;
+}
- return prefixSize;
+size_t FieldRef::commonPrefixSize(const FieldRef& other) const {
+ if (_size == 0 || other._size == 0) {
+ return 0;
}
- StringData FieldRef::dottedField( size_t offset ) const {
- return dottedSubstring(offset, numParts());
+ size_t maxPrefixSize = std::min(_size - 1, other._size - 1);
+ size_t prefixSize = 0;
+
+ while (prefixSize <= maxPrefixSize) {
+ if (getPart(prefixSize) != other.getPart(prefixSize)) {
+ break;
+ }
+ prefixSize++;
}
- StringData FieldRef::dottedSubstring(size_t startPart, size_t endPart) const {
- if (_size == 0 || startPart >= endPart || endPart > numParts())
- return StringData();
+ return prefixSize;
+}
- if (!_replacements.empty())
- reserialize();
- dassert(_replacements.empty());
+StringData FieldRef::dottedField(size_t offset) const {
+ return dottedSubstring(offset, numParts());
+}
- StringData result(_dotted);
+StringData FieldRef::dottedSubstring(size_t startPart, size_t endPart) const {
+ if (_size == 0 || startPart >= endPart || endPart > numParts())
+ return StringData();
- // Fast-path if we want the whole thing
- if (startPart == 0 && endPart == numParts())
- return result;
+ if (!_replacements.empty())
+ reserialize();
+ dassert(_replacements.empty());
- size_t startChar = 0;
- for (size_t i = 0; i < startPart; ++i) {
- startChar += getPart(i).size() + 1; // correct for '.'
- }
- size_t endChar = startChar;
- for (size_t i = startPart; i < endPart; ++i) {
- endChar += getPart(i).size() + 1;
- }
- // correct for last '.'
- if (endPart != numParts())
- --endChar;
+ StringData result(_dotted);
- return result.substr(startChar, endChar - startChar);
- }
+ // Fast-path if we want the whole thing
+ if (startPart == 0 && endPart == numParts())
+ return result;
- bool FieldRef::equalsDottedField( StringData other ) const {
- StringData rest = other;
+ size_t startChar = 0;
+ for (size_t i = 0; i < startPart; ++i) {
+ startChar += getPart(i).size() + 1; // correct for '.'
+ }
+ size_t endChar = startChar;
+ for (size_t i = startPart; i < endPart; ++i) {
+ endChar += getPart(i).size() + 1;
+ }
+ // correct for last '.'
+ if (endPart != numParts())
+ --endChar;
- for ( size_t i = 0; i < _size; i++ ) {
+ return result.substr(startChar, endChar - startChar);
+}
- StringData part = getPart( i );
+bool FieldRef::equalsDottedField(StringData other) const {
+ StringData rest = other;
- if ( !rest.startsWith( part ) )
- return false;
+ for (size_t i = 0; i < _size; i++) {
+ StringData part = getPart(i);
- if ( i == _size - 1 )
- return rest.size() == part.size();
+ if (!rest.startsWith(part))
+ return false;
- // make sure next thing is a dot
- if ( rest.size() == part.size() )
- return false;
+ if (i == _size - 1)
+ return rest.size() == part.size();
- if ( rest[part.size()] != '.' )
- return false;
+ // make sure next thing is a dot
+ if (rest.size() == part.size())
+ return false;
- rest = rest.substr( part.size() + 1 );
- }
+ if (rest[part.size()] != '.')
+ return false;
- return false;
+ rest = rest.substr(part.size() + 1);
}
- int FieldRef::compare(const FieldRef& other) const {
- const size_t toCompare = std::min(_size, other._size);
- for (size_t i = 0; i < toCompare; i++) {
- if (getPart(i) == other.getPart(i)) {
- continue;
- }
- return getPart(i) < other.getPart(i) ? -1 : 1;
- }
+ return false;
+}
- const size_t rest = _size - toCompare;
- const size_t otherRest = other._size - toCompare;
- if ((rest == 0) && (otherRest == 0)) {
- return 0;
- }
- else if (rest < otherRest ) {
- return -1;
- }
- else {
- return 1;
+int FieldRef::compare(const FieldRef& other) const {
+ const size_t toCompare = std::min(_size, other._size);
+ for (size_t i = 0; i < toCompare; i++) {
+ if (getPart(i) == other.getPart(i)) {
+ continue;
}
+ return getPart(i) < other.getPart(i) ? -1 : 1;
}
- void FieldRef::clear() {
- _size = 0;
- _variable.clear();
- _dotted.clear();
- _replacements.clear();
+ const size_t rest = _size - toCompare;
+ const size_t otherRest = other._size - toCompare;
+ if ((rest == 0) && (otherRest == 0)) {
+ return 0;
+ } else if (rest < otherRest) {
+ return -1;
+ } else {
+ return 1;
}
+}
- std::ostream& operator<<(std::ostream& stream, const FieldRef& field) {
- return stream << field.dottedField();
- }
+void FieldRef::clear() {
+ _size = 0;
+ _variable.clear();
+ _dotted.clear();
+ _replacements.clear();
+}
+
+std::ostream& operator<<(std::ostream& stream, const FieldRef& field) {
+ return stream << field.dottedField();
+}
-} // namespace mongo
+} // namespace mongo