tile/tile/base/string.h
2025-01-09 11:14:38 +08:00

157 lines
4.5 KiB
C++

#ifndef _TILE_BASE_STRING_H
#define _TILE_BASE_STRING_H
#pragma once
#include "tile/base/internal/format.h"
#include "tile/base/internal/meta.h"
#include "tile/base/optional.h"
#include "tile/base/slice.h"
#include <cctype>
#include <limits>
#include <string>
#include <vector>
namespace tile {
template<typename... Args>
std::string
Format(Slice fmt, Args &&...args)
{
return fmt::format(fmt.ToString(), std::forward<Args>(args)...);
}
template<typename OutputIt, typename... Args>
OutputIt
FormatTo(OutputIt out, Slice fmt, Args &&...args)
{
return fmt::format_to(out, fmt.ToString(), std::forward<Args>(args)...);
}
// 一些基本函数
bool StartsWith(Slice s, Slice prefix);
bool EndsWith(Slice s, Slice prefix);
bool StartsWithIgnoreCase(Slice s, Slice prefix);
bool EndsWithIgnoreCase(Slice s, Slice prefix);
void Replace(Slice from, Slice to, std::string *str, std::size_t count = std::numeric_limits<std::size_t>::max());
std::string Replace(Slice str, Slice from, Slice to, std::size_t count = std::numeric_limits<std::size_t>::max());
template<typename Pred = int(int)>
enable_if_t<!std::is_constructible<Slice, Pred>::value, Slice>
TrimLeft(Slice s, Pred pred = isspace)
{
while (!s.empty() && pred(s[0])) { s.RemovePrefix(1); }
return s;
}
template<typename Pred = int(int)>
enable_if_t<!std::is_constructible<Slice, Pred>::value, Slice>
TrimRight(Slice s, Pred pred = isspace)
{
while (!s.empty() && pred(s[s.size() - 1])) { s.RemoveSuffix(1); }
return s;
}
template<typename Pred = int(int)>
enable_if_t<!std::is_constructible<Slice, Pred>::value, Slice>
Trim(Slice s, Pred pred = isspace)
{
return TrimRight(TrimLeft(s, pred), pred);
}
template<typename T>
enable_if_t<std::is_constructible<Slice, T>::value, Slice>
TrimLeft(Slice s, T slice_like)
{
Slice cutset(slice_like);
return TrimLeft(s, [&cutset](char c) { return cutset.find(c) != Slice::npos; });
}
template<typename T>
enable_if_t<std::is_constructible<Slice, T>::value, Slice>
TrimRight(Slice s, T slice_like)
{
Slice cutset(slice_like);
return TrimRight(s, [&cutset](char c) { return cutset.find(c) != Slice::npos; });
}
template<typename T>
enable_if_t<std::is_constructible<Slice, T>::value, Slice>
Trim(Slice s, T slice_like)
{
Slice cutset(slice_like);
return Trim(s, [&cutset](char c) { return cutset.find(c) != Slice::npos; });
}
std::vector<Slice> Split(Slice s,
char delim,
bool keep_empty = false,
std::size_t max_split_parts = std::numeric_limits<std::size_t>::max());
std::vector<Slice> Split(Slice s,
Slice delim,
bool keep_empty = false,
std::size_t max_split_parts = std::numeric_limits<std::size_t>::max());
std::string Join(const std::vector<std::string> &parts, Slice delim);
std::string Join(const std::vector<Slice> &parts, Slice delim);
std::string Join(const std::initializer_list<Slice> &parts, Slice delim);
char ToUpper(char c);
char ToLower(char c);
void ToUpper(std::string *str);
void ToLower(std::string *str);
std::string ToUpper(Slice s);
std::string ToLower(Slice s);
bool Equals(Slice a, Slice b, std::size_t len = std::numeric_limits<std::size_t>::max());
bool EqualsIgnoreCase(Slice a, Slice b, std::size_t len = std::numeric_limits<std::size_t>::max());
// TryParse
template<typename T, typename = void>
struct TryParseTraits;
template<typename T, typename... Args>
std::optional<T>
TryParse(Slice s, const Args &...args)
{
return TryParseTraits<T>::TryParse(s, args...);
}
template<typename T, typename>
struct TryParseTraits {
template<typename... Args>
static std::optional<T> TryParse(Slice s, const Args &...args)
{
return TryParse(std::common_type<T>(), s, args...);
}
};
// String to bool
// 1. "true" or "false"
// 2. "yes" or "no"
// 3. "on" or "off"
// 4. non-zero or zero
template<>
struct TryParseTraits<bool> {
static std::optional<bool> TryParse(Slice s, bool recognizes_alpbabet_symbol = true, bool ignore_case = true);
};
// string to number
template<typename T>
struct TryParseTraits<T, typename std::enable_if<std::is_integral<T>::value>::type> {
static std::optional<T> TryParse(Slice s, int base = 10);
};
// string to decimal
template<typename T>
struct TryParseTraits<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
static std::optional<T> TryParse(Slice s);
};
}// namespace tile
#endif// _TILE_BASE_STRING_H