Commit 00f81257 authored by tqcq's avatar tqcq
Browse files

fix StrSplit

parent f1f1f4b2
Loading
Loading
Loading
Loading

'

0 → 100644
+131 −0
Original line number Diff line number Diff line
#include "sled/strings/utils.h"
#include <sstream>
#include <string.h>

namespace sled {

char
ToLower(char c)
{
    return ::tolower(c);
}

char
ToUpper(char c)
{
    return ::toupper(c);
}

std::string
ToLower(const std::string &str)
{
    std::stringstream ss;
    for (auto &ch : str) { ss << ToLower(ch); }
    return ss.str();
}

std::string
ToUpper(const std::string &str)
{
    std::stringstream ss;
    for (auto &ch : str) { ss << ToUpper(ch); }
    return ss.str();
}

std::string
StrJoin(const std::vector<std::string> &strings, const std::string &delim, bool skip_empty)
{
    if (strings.empty()) { return ""; }

    std::stringstream ss;
    size_t i = 0;
    while (skip_empty && i < strings.size() && strings[i].empty()) { ++i; }
    if (i < strings.size()) { ss << strings[i++]; }
    for (; i < strings.size(); ++i) {
        if (skip_empty && strings[i].empty()) { continue; }
        ss << delim << strings[i];
    }
    return ss.str();
}

std::vector<std::string>
StrSplit(const std::string &str, const std::string &delim, bool skip_empty)
{
    std::vector<std::string> result;
    if (str.empty()) { return result; }

    size_t start    = 0;
    size_t next_pos = str.find_first_of(delim, start);
    while (next_pos != std::string::npos) {
        if ((!skip_empty && next_pos == start) || next_pos > start) {
            result.emplace_back(str.begin() + start, str.begin() + next_pos);
        }

        if (!skip_empty) {
            start    = next_pos + 1;
            next_pos = str.find_first_of(delim, start);
        } else {
            start = str.find_first_not_of(delim, next_pos);
            if (start == std::string::npos) {
                // all remaining characters are delimiters
                break;
            }
            next_pos = str.find_first_of(delim, start);
        }
    }

    if (start < str.size()) { result.emplace_back(str.substr(start)); }
    return result;
}

std::string
Trim(const std::string &str, const std::string &chars)
{
    return TrimLeft(TrimRight(str, chars), chars);
}

std::string
TrimLeft(const std::string &str, const std::string &chars)
{
    size_t start = str.find_first_not_of(chars);
    return start == std::string::npos ? "" : str.substr(start);
}

std::string
TrimRight(const std::string &str, const std::string &chars)
{
    size_t end = str.find_last_not_of(chars);
    return end == std::string::npos ? "" : str.substr(0, end + 1);
}

bool
EndsWith(const std::string &str, const std::string &suffix)
{
    return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}

bool
StartsWith(const std::string &str, const std::string &prefix)
{
    return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
}

bool
EndsWithIgnoreCase(const std::string &str, const std::string &suffix)
{
    return EndsWith(ToLower(str), ToLower(suffix));
}

bool
StartsWithIgnoreCase(const std::string &str, const std::string &prefix)
{
    return StartsWith(ToLower(str), ToLower(prefix));
}

bool
EqualsIgnoreCase(const std::string &lhs, const std::string &rhs)
{
    return ToLower(lhs) == ToLower(rhs);
}

}// namespace sled
+48 −15
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ target_include_directories(sled PUBLIC src/ 3party/eigen 3party/inja
target_sources(
  sled
  PRIVATE src/sled/async/async.cc
          src/sled/debugging/symbolize.cc
          src/sled/filesystem/path.cc
          src/sled/log/log.cc
          src/sled/network/async_resolver.cc
@@ -112,6 +113,32 @@ if(SLED_BUILD_BENCHMARK)
                                               benchmark::benchmark_main)
endif(SLED_BUILD_BENCHMARK)

function(sled_add_test)
  set(prefix SLED_TEST)
  # set(options INC_DIRS LIBS)
  set(one_value_keywords NAME)
  set(multi_value_keywords SRCS INC_DIRS LIBS)
  cmake_parse_arguments("${prefix}" "${options}" "${one_value_keywords}"
                        "${multi_value_keywords}" ${ARGN})

  message(WARNING "SLED_TEST_NAME: ${SLED_TEST_NAME}")
  message(WARNING "SLED_TEST_SRCS: ${SLED_TEST_SRCS}")
  message(WARNING "SLED_TEST_LIBS: ${SLED_TEST_LIBS}")
  add_executable(${SLED_TEST_NAME} ${SLED_TEST_SRCS})

  if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(EXTRA_FLAGS -Wthread-safety -g -fsanitize=address
                    -fno-omit-frame-pointer -fno-optimize-sibling-calls)
    target_compile_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})

    target_link_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})
  endif()
  target_include_directories(${SLED_TEST_NAME} PRIVATE ${SLED_TEST_INC_DIRS})
  target_link_libraries(${SLED_TEST_NAME} PRIVATE ${SLED_TEST_LIBS}
                                                  GTest::gtest)
  add_test(NAME ${SLED_TEST_NAME} COMMAND ${SLED_TEST_NAME})
endfunction()

if(SLED_BUILD_TESTS)
  include(FetchContent)
  FetchContent_Declare(
@@ -119,17 +146,16 @@ if(SLED_BUILD_TESTS)
    URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
  )
  FetchContent_MakeAvailable(googletest)
  add_executable(
    sled_tests
    # src/sled/exec/just_test.cc

  sled_add_test(
    NAME
    sled_base_test
    SRCS
    src/sled/async/async_test.cc
    src/sled/any_test.cc
    src/sled/filesystem/path_test.cc
    # src/sled/futures/promise_test.cc
    src/sled/futures/detail/just_test.cc
    src/sled/log/fmt_test.cc
    # src/sled/profiling/profiling_test.cc
    src/sled/strings/base64_test.cc
    src/sled/synchronization/sequence_checker_test.cc
    src/sled/cleanup_test.cc
    src/sled/status_test.cc
@@ -137,16 +163,23 @@ if(SLED_BUILD_TESTS)
    src/sled/system/fiber/fiber_test.cc
    src/sled/system/thread_pool_test.cc
    src/sled/rx_test.cc
    src/sled/uri_test.cc)
  if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(EXTRA_FLAGS -Wthread-safety -g -fsanitize=address
                    -fno-omit-frame-pointer -fno-optimize-sibling-calls)
    target_compile_options(sled_tests PRIVATE ${EXTRA_FLAGS})
    src/sled/uri_test.cc
    LIBS
    sled
    GTest::gtest_main)

    target_link_options(sled_tests PRIVATE ${EXTRA_FLAGS})
  endif()
  target_link_libraries(sled_tests PRIVATE sled GTest::gtest GTest::gtest_main)
  add_test(NAME sled_tests COMMAND sled_tests)
  sled_add_test(
    NAME
    sled_strings_test
    SRCS
    src/sled/strings/utils_test.cc
    src/sled/strings/base64_test.cc
    LIBS
    sled
    GTest::gtest_main)

  sled_add_test(NAME sled_symbolize_test SRCS
                src/sled/debugging/symbolize_test.cc LIBS sled)
endif(SLED_BUILD_TESTS)

if(SLED_BUILD_FUZZ)
+25 −0
Original line number Diff line number Diff line
#include "sled/debugging/symbolize.h"

#ifdef _WIN32
void
InitializeSymbolizer(const char *argv0)
{}

bool
Symbolize(const void *pc, char *out, int out_size)
{
    return false;
}
#elif defined(__APPLE__)
void
InitializeSymbolizer(const char *argv0)
{}

bool
Symbolize(const void *pc, char *out, int out_size)
{
    return false;
}
#elif defined(__linux__)
#include "sled/debugging/symbolize_elf.inc"
#endif
+10 −0
Original line number Diff line number Diff line
#ifndef SLED_DEBUGGING_SYMBOLIZE_H
#define SLED_DEBUGGING_SYMBOLIZE_H
#pragma once

namespace sled {
void InitializeSymbolizer(const char *argv0);
bool Symbolize(const void *pc, char *out, int out_size);
bool ReadAddrMap();
}// namespace sled
#endif// SLED_DEBUGGING_SYMBOLIZE_H
+140 −0
Original line number Diff line number Diff line
#include <array>
#include <cxxabi.h>
#include <dlfcn.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <link.h>
#include <sled/log/log.h>
#include <sled/strings/utils.h>
#include <sstream>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

namespace sled {

static constexpr char kTag[] = "symbolizer";
static char *g_exe           = nullptr;

static const uint64_t
GetHex(const char *start, const char *end)
{
    uint64_t hex = 0;
    for (const char *p = start; p < end; ++p) {
        int ch = *p;
        if (ch >= '0' && ch <= '9') {
            hex = hex * 16 + (ch - '0');
        } else if (ch >= 'a' && ch <= 'f') {
            hex = hex * 16 + (ch - 'a' + 10);
        } else if (ch >= 'A' && ch <= 'F') {
            hex = hex * 16 + (ch - 'A' + 10);
        } else {
            break;
        }
    }

    return hex;
}

static const uint64_t
GetHex(const std::string &str)
{
    return GetHex(str.c_str(), str.c_str() + str.size());
}

struct ObjFile {
    ObjFile() : filename(nullptr), start_addr(nullptr), end_addr(nullptr), offset(0), fd(-1), elf_type(-1)
    {
        memset(&elf_header, 0, sizeof(elf_header));
        memset(phdrs.data(), 0, sizeof(ElfW(Phdr)) * phdrs.size());
    }

    char *filename;
    const void *start_addr;
    const void *end_addr;
    uint64_t offset;

    int fd;
    int elf_type;
    ElfW(Ehdr) elf_header;

    std::array<ElfW(Phdr), 16> phdrs;
};

std::string
ReadFullFile(int fd)
{
    std::stringstream ss;
    char buf[4096];
    ssize_t n;
    while ((n = read(fd, buf, sizeof(buf))) > 0) { ss.write(buf, n); }
    return ss.str();
}

bool
ReadAddrMap()
{
    char maps_path[80];
    snprintf(maps_path, sizeof(maps_path), "/proc/self/task/%d/maps", getpid());
    int maps_fd;
    do {
        maps_fd = open(maps_path, O_RDONLY);
    } while (maps_fd < 0 && errno == EINTR);

    if (maps_fd < 0) {
        LOGE(kTag, "open {} failed, {}", maps_path, strerror(errno));
        return false;
    }

    std::string full_file = ReadFullFile(maps_fd);
    auto lines            = sled::StrSplit(full_file, "\n");

    // maps start_addr-end_addr permission offset dev inode pathname
    for (const auto &line : lines) {
        auto fields = sled::StrSplit(line, " \n\t", true);
        if (fields.size() < 6) { continue; }
        auto addrs = sled::StrSplit(fields[0], "-", false);

        uint64_t start_addr = GetHex(addrs[0]);
        uint64_t end_addr   = GetHex(addrs[1]);
        uint64_t offset     = GetHex(fields[2]);
        LOGD(kTag, "addr: {}-{} {} {} {}", start_addr, end_addr, offset, fields[1], fields[5]);
    }

    return true;
}

class Symbolizer {};

void
InitializeSymbolizer(const char *argv0)
{
    if (g_exe) {
        free(g_exe);
        g_exe = nullptr;
    }

    if (argv0 && argv0[0] != '\0') { g_exe = strdup(argv0); }
}

bool
Symbolize(const void *pc, char *out, int out_size)
{
    Dl_info info;
    if (!dladdr(pc, &info)) { return false; }
    if (info.dli_fname && out_size > 0) {
        strncpy(out, info.dli_fname, out_size);

        const auto end_pos = static_cast<size_t>(out_size) - 1;
        if (out[end_pos] != '\0') {
            // add ...
            out[end_pos] = '\0';
        }
    }

    return true;
}
}// namespace sled
Loading