void FieldRef::parse(const StringData& dottedField) { if (dottedField.size() == 0) { return; } if (_size != 0) { clear(); } // 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::parse(const StringData& path) { if (path.size() == 0) { return; } 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; } break; } }