|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "mystring.h"
1.1.1.2 root 8: #include <algorithm>
1.1 root 9:
10: std::string
11: string_format(const char *fmt, ...)
12: {
13: va_list ap;
14: char *buf;
15:
16: va_start(ap, fmt);
17: vasprintf(&buf, fmt, ap);
18: va_end(ap);
19: std::string rv(buf);
20: free(buf);
21:
22: return rv;
23: }
24:
1.1.1.2 root 25: // 文字列 str から先頭の連続する空白文字を取り除いた新しい文字列を返す。
26: std::string
27: string_ltrim(const std::string& str)
28: {
29: auto it = str.begin();
30: for (; it != str.end(); it++) {
31: if (!isspace(*it))
32: break;
33: }
34: return std::string(it, str.end());
35: }
36:
37: // 文字列 str から末尾の連続する空白文字を取り除く (str を書き換える)。
38: void
39: string_rtrim(std::string& str)
40: {
41: while (isspace(*str.rbegin())) {
42: str.pop_back();
43: }
44: }
45:
46: // 文字列 str から末尾の連続する空白文字を取り除く (str を書き換える)。
47: void
48: rtrim(char *str)
49: {
50: char *p = strchr(str, '\0');
1.1.1.5 ! root 51: while (--p >= str && isspace((int)*p)) {
1.1.1.2 root 52: *p = '\0';
53: }
54: }
55:
1.1.1.5 ! root 56: // 文字列 str から先頭と末尾の連続する空白文字を取り除いた新しい文字列を返す。
! 57: std::string
! 58: string_trim(const std::string& str)
! 59: {
! 60: int s = 0;
! 61: int e = str.size();
! 62:
! 63: for (; s < e; s++) {
! 64: if (!isspace(str[s]))
! 65: break;
! 66: }
! 67: for (e--; e >= s; e--) {
! 68: if (!isspace(str[e]))
! 69: break;
! 70: }
! 71:
! 72: return str.substr(s, e - s + 1);
! 73: }
! 74:
1.1.1.2 root 75: // 文字列 src 中の ASCII 大文字を小文字にした新しい文字列を返す。
76: std::string
77: string_tolower(const std::string& src)
78: {
79: std::string dst(src);
80: std::transform(dst.begin(), dst.end(), dst.begin(),
81: [](unsigned char c){ return std::tolower(c); });
82: return dst;
83: }
84:
1.1.1.4 root 85: // 文字列 lhs の先頭が rhs と大文字小文字の区別なしで一致すれば true を返す。
86: // ASCII 専用。
87: // C++20 の starts_with に似せておく。
88: bool
89: starts_with_ignorecase(const std::string& lhs, const std::string& rhs)
90: {
91: if (lhs.length() < rhs.length()) {
92: return false;
93: }
94: #if 0
95: return std::equal(
96: lhs.begin(), lhs.begin() + rhs.length(),
97: rhs.begin(),
98: [](std::string::value_type l, std::string::value_type r) {
99: return std::tolower(l) == std::tolower(r);
100: }
101: );
102: #else
103: // こっちのほうが分かりやすいよな
104: return strncasecmp(lhs.c_str(), rhs.c_str(), rhs.length()) == 0;
105: #endif
106: }
107:
108: // 文字列 str (長さ len) を文字 c で分割したリストを返す。
109: std::vector<std::string>
1.1.1.5 ! root 110: string_split(const char *str, int len, char c, int nlimit)
1.1.1.4 root 111: {
112: std::vector<std::string> list;
113:
1.1.1.5 ! root 114: // 空文字列なら空リスト
! 115: if (len == 0) {
! 116: return list;
! 117: }
! 118:
! 119: int pos = 0;
! 120: int end = 0;
! 121:
! 122: for (; ; pos = end + 1) {
! 123: // 上限に達するならこれ以降は一要素として返す
! 124: if (nlimit > 0 && list.size() >= nlimit - 1) {
! 125: list.emplace_back(str + pos, len - pos);
! 126: break;
! 127: }
! 128:
1.1.1.4 root 129: const char *p = strchr(str + pos, c);
130: if (p) {
131: end = p - str;
132: } else {
133: end = len;
134: }
135:
136: list.emplace_back(str + pos, end - pos);
1.1.1.5 ! root 137: if (p == NULL)
! 138: break;
1.1.1.4 root 139: }
140:
141: return list;
142: }
143:
1.1 root 144: #if 0
145: #include <cstdio>
146: #include <sys/time.h>
147: int main()
148: {
149: std::string s0 = string_format("%d_%d", 0, 1);
150: if (s0 != "0_1") {
151: printf("error\n");
152: return 1;
153: }
154: timeval start, end, result;
155: gettimeofday(&start, NULL);
156: for (int i = 0; i < 100000; i++) {
157: std::string s = string_format("%d_%d", i, i);
158: }
159: gettimeofday(&end, NULL);
160: timersub(&end, &start, &result);
161: long long t = (result.tv_sec) * 1000000 + result.tv_usec;
162: printf("%d.%03d\n", (int)t / 1000, (int)t % 1000);
163: return 0;
164: }
165: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.