StringPiece trim(StringPiece sp, StringPiece chars) { for (; !sp.empty() && chars.find(sp.front()) != StringPiece::npos; ) { sp.pop_front(); } for (; !sp.empty() && chars.find(sp.back()) != StringPiece::npos; ) { sp.pop_back(); } return sp; }
Expected<IPAddress, IPAddressFormatError> IPAddress::tryFromString( StringPiece str) noexcept { // need to check for V4 address second, since IPv4-mapped IPv6 addresses may // contain a period if (str.find(':') != string::npos) { return IPAddressV6::tryFromString(str); } else if (str.find('.') != string::npos) { return IPAddressV4::tryFromString(str); } else { return makeUnexpected(IPAddressFormatError::UNSUPPORTED_ADDR_FAMILY); } }
void SplitStringKeepEmpty( const StringPiece& full, const StringPiece& delim, std::vector<std::string>* result) { // 单个字符的分隔符转调字符版本的分割函数,要快一些 if (delim.length() == 1) { SplitStringKeepEmpty(full, delim[0], result); return; } result->clear(); if (full.empty() || delim.empty()) return; size_t prev_pos = 0; size_t pos; std::string token; while ((pos = full.find(delim, prev_pos)) != std::string::npos) { token.assign(full.data() + prev_pos, pos - prev_pos); result->push_back(token); prev_pos = pos + delim.length(); } token.assign(full.data() + prev_pos, full.length() - prev_pos); result->push_back(token); }
void DoSplitLines( const StringPiece& full, std::vector<StringType>* result, bool keep_line_endling ) { result->clear(); size_t prev_pos = 0; size_t pos; StringType token; while ((pos = full.find('\n', prev_pos)) != std::string::npos) { token.assign(full.data() + prev_pos, pos - prev_pos + 1); if (!keep_line_endling) RemoveLineEnding(&token); result->push_back(token); prev_pos = pos + 1; } if (prev_pos < full.size()) { token.assign(full.data() + prev_pos, full.length() - prev_pos); if (!keep_line_endling) RemoveLineEnding(&token); result->push_back(token); } }
void parseMessage(StringPiece msg, size_t* threadID, size_t* messageIndex) { // Validate and strip off the message prefix and suffix constexpr StringPiece prefix{"thread "}; if (!msg.startsWith(prefix)) { throw std::runtime_error("bad message prefix"); } msg.advance(prefix.size()); if (!msg.endsWith(kMsgSuffix)) { throw std::runtime_error("bad message suffix"); } msg.subtract(kMsgSuffix.size()); // Parse then strip off the thread index auto threadIDEnd = msg.find(' '); if (threadIDEnd == StringPiece::npos) { throw std::runtime_error("no middle found"); } *threadID = folly::to<size_t>(msg.subpiece(0, threadIDEnd)); msg.advance(threadIDEnd); // Validate that the middle of the message is what we expect, // then strip it off constexpr StringPiece middle{" message "}; if (!msg.startsWith(middle)) { throw std::runtime_error("bad message middle"); } msg.advance(middle.size()); // Parse the message index *messageIndex = folly::to<size_t>(msg); }
void messageReceived(StringPiece msg) { if (msg.endsWith(" log messages discarded: " "logging faster than we can write")) { auto discardCount = folly::to<size_t>(msg.subpiece(0, msg.find(' '))); XLOG(DBG3, "received discard notification: ", discardCount); numDiscarded_ += discardCount; ++discardEventsSeen_; return; } size_t threadID = 0; size_t messageIndex = 0; try { parseMessage(msg, &threadID, &messageIndex); } catch (const std::exception& ex) { ++numUnableToParse_; XLOG(ERR, "unable to parse log message: ", msg); return; } auto& data = perThreadReadData_[threadID]; data.numMessagesRead++; if (messageIndex > data.lastId) { data.lastId = messageIndex; } else { ++numOutOfOrder_; XLOG(ERR) << "received out-of-order messages from writer " << threadID << ": " << messageIndex << " received after " << data.lastId; } }
bool HttpRequest::ParseStartLine(const StringPiece& data, HttpMessage::ErrorCode* error) { ErrorCode error_placeholder; if (error == NULL) error = &error_placeholder; static const size_t kMinHttpMethodLength = 3; size_t pos = data.find(' ', kMinHttpMethodLength); if (pos == StringPiece::npos) { *error = ERROR_START_LINE_NOT_COMPLETE; return false; } StringPiece method = data.substr(0, pos); StringTrim(&method); m_method = GetMethodByName(method); if (m_method == METHOD_UNKNOWN) { *error = ERROR_METHOD_NOT_FOUND; return false; } size_t prev_pos = pos + 1; pos = data.find(' ', prev_pos); StringPiece uri; if (pos == StringPiece::npos) { uri = data.substr(prev_pos); } else { uri = data.substr(prev_pos, pos - prev_pos); } StringTrim(&uri); uri.copy_to_string(&m_uri); if (pos != StringPiece::npos) { StringPiece version = data.substr(pos); StringTrim(&version); if (!ParseVersion(version)) { *error = ERROR_VERSION_UNSUPPORTED; return false; } } return true; }
size_t ReplaceAllChars(std::string* s, const StringPiece& from, char to) { size_t num_replaced = 0; size_t length = s->length(); for (size_t i = 0; i < length; ++i) { if (from.find((*s)[i]) != std::string::npos) { (*s)[i] = to; ++num_replaced; } } return num_replaced; }
// Replace the first "old" pattern with the "new" pattern in a string std::string ReplaceFirst( const StringPiece& s, const StringPiece& oldsub, const StringPiece& newsub) { if (oldsub.empty()) return s.as_string(); std::string res; std::string::size_type pos = s.find(oldsub); if (pos == std::string::npos) return s.as_string(); else { res.append(s.data(), pos); res.append(newsub.data(), newsub.size()); res.append(s.data() + pos + oldsub.size(), s.length() - pos - oldsub.size()); } return res; }
// Replace all the "old" pattern with the "new" pattern in a string std::string ReplaceAll(const StringPiece& s, const StringPiece& oldsub, const StringPiece& newsub) { if (oldsub.empty()) return s.as_string(); std::string res; std::string::size_type start_pos = 0; std::string::size_type pos; do { pos = s.find(oldsub, start_pos); if (pos == std::string::npos) { break; } res.append(s.data() + start_pos, pos - start_pos); res.append(newsub.data(), newsub.size()); start_pos = pos + oldsub.size(); } while (true); res.append(s.data() + start_pos, s.length() - start_pos); return res; }
static inline void SplitUsingStringDelimiterToIterator(const StringPiece& full, const char* delim, ITR& result) { if (full.empty()) { return; } if (delim[0] == '\0') { *result++ = full.as_string(); return; } // Optimize the common case where delim is a single character. if (delim[1] == '\0') { SplitStringToIteratorUsing<StringType>(full, delim, result); return; } size_t delim_length = strlen(delim); for (size_t begin_index = 0; begin_index < full.size();) { size_t end_index = full.find(delim, begin_index); if (end_index == std::string::npos) { *result++ = full.substr(begin_index).as_string(); return; } if (end_index > begin_index) { StringType value(full.data() + begin_index, end_index - begin_index); *result++ = value; } begin_index = end_index + delim_length; } }
/** 功能: 把一个字符串划分成多个字符串 * 参数: * 输入参数 const StringPiece& full 主字符串 * 输入参数 const StringPiece& delim 字符串分界符号 * 输出参数 std::vector<std::string>& result 分解后的结果 */ void SplitStringKeepEmpty( const StringPiece& full, char delim, std::vector<std::string>* result) { result->clear(); if (full.empty()) return; size_t prev_pos = 0; size_t pos; std::string token; while ((pos = full.find(delim, prev_pos)) != std::string::npos) { token.assign(full.data() + prev_pos, pos - prev_pos); result->push_back(token); prev_pos = pos + 1; } token.assign(full.data() + prev_pos, full.length() - prev_pos); result->push_back(token); }
size_t HttpHeaders::Parse(const StringPiece& data, int* error) { int error_placeholder; if (error == NULL) error = &error_placeholder; // Starts with empty line means empty headers. if (StringStartsWith(data, "\n") || StringStartsWith(data, "\r\n")) { m_headers.clear(); return (data[0] == '\r') + 1; // sizeof \n or \r\n } size_t end_pos; size_t tail_size; if ((end_pos = data.find("\r\n\r\n")) != std::string::npos) { tail_size = 4; } else if ((end_pos = data.find("\n\n")) != std::string::npos) { tail_size = 2; } else { *error = HttpMessage::ERROR_MESSAGE_NOT_COMPLETE; return 0; } std::vector<StringPiece> lines; SplitLines(data.substr(0, end_pos + tail_size), &lines); if (lines.empty()) { *error = HttpMessage::ERROR_MESSAGE_NOT_COMPLETE; return 0; } m_headers.clear(); // Skip the head line and the last line(empty but '\n') for (int i = 0; i < static_cast<int>(lines.size() - 1); ++i) { StringPiece line = lines[i]; size_t pos = line.find(':'); if (pos != StringPiece::npos) { StringPiece name = line.substr(0, pos); StringPiece value = line.substr(pos + 1); StringTrim(&name); StringTrim(&value); // Push an empty element and modify it to avoid copy. m_headers.push_back(std::pair<std::string, std::string>()); std::pair<std::string, std::string> &header = m_headers.back(); name.copy_to_string(&header.first); value.copy_to_string(&header.second); } else { if (!lines[i].empty()) { VLOG(3) << "Invalid http header" << lines[i] << ", ignore"; } else { *error = HttpMessage::ERROR_FIELD_NOT_COMPLETE; m_headers.clear(); return 0; } } } *error = HttpMessage::SUCCESS; return end_pos + tail_size; }