Beispiel #1
0
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;
}
Beispiel #2
0
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);
  }
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
    }
}
Beispiel #5
0
  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);
  }
Beispiel #6
0
  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;
    }
  }
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
// 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;
}
Beispiel #10
0
// 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;
}
Beispiel #11
0
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;
    }
}
Beispiel #12
0
/** 功能: 把一个字符串划分成多个字符串
 *  参数:
 *  输入参数 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);
}
Beispiel #13
0
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;
}