157 lines
4.5 KiB
C++
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
|