File indexing completed on 2024-05-19 16:50:20
0001 /***************************************************************************** 0002 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify * 0005 * it under the terms of the GNU Lesser General Public License as * 0006 * published by the Free Software Foundation; either version 2.1 of the * 0007 * License, or (at your option) version 3, or any later version accepted * 0008 * by the membership of KDE e.V. (or its successor approved by the * 0009 * membership of KDE e.V.), which shall act as a proxy defined in * 0010 * Section 6 of version 3 of the license. * 0011 * * 0012 * This program is distributed in the hope that it will be useful, * 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0015 * Lesser General Public License for more details. * 0016 * * 0017 * You should have received a copy of the GNU Lesser General Public * 0018 * License along with this library. If not, * 0019 * see <http://www.gnu.org/licenses/>. * 0020 *****************************************************************************/ 0021 0022 #define __QTC_UTILS_STRS_INTERNAL__ 0023 0024 #include "strs.h" 0025 #include "number.h" 0026 0027 namespace QtCurve { 0028 namespace Str { 0029 0030 template<bool allocated> 0031 char* 0032 vformat(char *buff, size_t *_size, const char *fmt, va_list ap) 0033 { 0034 if (!buff || !_size || !*_size) { 0035 char *res = nullptr; 0036 vasprintf(&res, fmt, ap); 0037 return res; 0038 } 0039 va_list _ap; 0040 va_copy(_ap, ap); 0041 size_t size = *_size; 0042 size_t new_size = vsnprintf(buff, size, fmt, ap) + 1; 0043 if (new_size > size) { 0044 new_size = alignTo(new_size, 1024); 0045 if (allocated) { 0046 buff = (char*)realloc(buff, new_size); 0047 } else { 0048 buff = (char*)malloc(new_size); 0049 } 0050 *_size = new_size; 0051 new_size = vsnprintf(buff, new_size, fmt, _ap); 0052 } 0053 return buff; 0054 } 0055 0056 template QTC_EXPORT char *vformat<true>(char *buff, size_t *size, 0057 const char *fmt, va_list ap); 0058 template QTC_EXPORT char *vformat<false>(char *buff, size_t *size, 0059 const char *fmt, va_list ap); 0060 0061 template<> 0062 QTC_EXPORT double 0063 convert<double>(const char *str, const double &def, bool *is_def) 0064 { 0065 if (!str) { 0066 qtcAssign(is_def, true); 0067 return def; 0068 } 0069 str += strspn(str, " \t\b\n\f\v"); 0070 char *end = nullptr; 0071 double res = strtod(str, &end); 0072 if (end == str) { 0073 qtcAssign(is_def, true); 0074 res = def; 0075 } else { 0076 qtcAssign(is_def, false); 0077 } 0078 return res; 0079 } 0080 template double convert<double>(const char*, const double&, bool *is_def); 0081 0082 template<> 0083 QTC_EXPORT long 0084 convert<long>(const char *str, const long &def, bool *is_def) 0085 { 0086 if (!str) { 0087 qtcAssign(is_def, true); 0088 return def; 0089 } 0090 str += strspn(str, " \t\b\n\f\v"); 0091 char *end = nullptr; 0092 long res = strtol(str, &end, 0); 0093 if (end == str) { 0094 qtcAssign(is_def, true); 0095 res = def; 0096 } else { 0097 qtcAssign(is_def, false); 0098 } 0099 return res; 0100 } 0101 template long convert<long>(const char*, const long&, bool *is_def); 0102 0103 template<> 0104 QTC_EXPORT bool 0105 convert<bool>(const char *str, const bool &def, bool *is_def) 0106 { 0107 qtcAssign(is_def, false); 0108 if (str && *str) { 0109 if (def) { 0110 return noneOf<CaseCmp>(str, "0", "f", "false", "off"); 0111 } else { 0112 return oneOf<CaseCmp>(str, "1", "t", "true", "on"); 0113 } 0114 } 0115 return def; 0116 } 0117 template bool convert<bool>(const char*, const bool&, bool *is_def); 0118 0119 } 0120 0121 namespace StrList { 0122 0123 QTC_EXPORT void 0124 _forEach(const char *str, char delim, char escape, 0125 const std::function<bool(const char*, size_t)> &func) 0126 { 0127 QTC_RET_IF_FAIL(str); 0128 Str::Buff<1024> buff; 0129 if (qtcUnlikely(escape == delim)) { 0130 escape = '\0'; 0131 } 0132 const char key[] = {delim, escape, '\0'}; 0133 const char *p = str; 0134 while (true) { 0135 size_t len = 0; 0136 while (true) { 0137 size_t sub_len = strcspn(p, key); 0138 buff.resize(len + sub_len + 2); 0139 memcpy(buff.get() + len, p, sub_len); 0140 len += sub_len; 0141 p += sub_len; 0142 if (escape && *p == escape) { 0143 buff[len] = p[1]; 0144 if (qtcUnlikely(!p[1])) { 0145 p++; 0146 break; 0147 } 0148 len++; 0149 p += 2; 0150 } else { 0151 buff[len] = '\0'; 0152 break; 0153 } 0154 } 0155 if (!func(buff.get(), len) || !*p) { 0156 break; 0157 } 0158 p++; 0159 } 0160 } 0161 } 0162 0163 } 0164 0165 QTC_EXPORT void* 0166 qtcStrLoadList(const char *str, char delim, char escape, size_t size, 0167 size_t *_nele, void *buff, size_t max_len, 0168 QtcListEleLoader loader, void *data) 0169 { 0170 QTC_RET_IF_FAIL(_nele && size && loader && str, nullptr); 0171 size_t nele = *_nele; 0172 size_t offset = 0; 0173 if (!(buff && nele)) { 0174 nele = 16; 0175 buff = malloc(16 * size); 0176 } 0177 QtCurve::StrList::forEach( 0178 str, delim, escape, [&] (const char *str, size_t len) { 0179 if (nele <= offset) { 0180 nele += 8; 0181 buff = (char*)realloc(buff, nele * size); 0182 } 0183 if (loader((char*)buff + offset * size, str, len, data)) { 0184 offset++; 0185 if (max_len && offset >= max_len) { 0186 return false; 0187 } 0188 } 0189 return true; 0190 }); 0191 *_nele = offset; 0192 if (!*_nele) { 0193 free(buff); 0194 return nullptr; 0195 } 0196 return buff; 0197 } 0198 0199 static bool 0200 qtcStrListStrLoader(void *ele, const char *str, size_t len, void *data) 0201 { 0202 const char *def = (const char*)data; 0203 if (def && !str[0]) { 0204 *(char**)ele = strdup(def); 0205 } else { 0206 *(char**)ele = QtCurve::Str::dup(nullptr, str, len); 0207 } 0208 return true; 0209 } 0210 0211 QTC_EXPORT char** 0212 qtcStrLoadStrList(const char *str, char delim, char escape, size_t *nele, 0213 char **buff, size_t max_len, const char *def) 0214 { 0215 return (char**)qtcStrLoadList(str, delim, escape, sizeof(char*), nele, buff, 0216 max_len, qtcStrListStrLoader, (void*)def); 0217 } 0218 0219 static bool 0220 qtcStrListIntLoader(void *ele, const char *str, size_t, void *data) 0221 { 0222 *(long*)ele = QtCurve::Str::convert(str, (long)(intptr_t)data); 0223 return true; 0224 } 0225 0226 QTC_EXPORT long* 0227 qtcStrLoadIntList(const char *str, char delim, char escape, size_t *nele, 0228 long *buff, size_t max_len, long def) 0229 { 0230 return (long*)qtcStrLoadList(str, delim, escape, sizeof(long), nele, buff, 0231 max_len, qtcStrListIntLoader, 0232 (void*)(intptr_t)def); 0233 } 0234 0235 static bool 0236 qtcStrListFloatLoader(void *ele, const char *str, size_t, void *data) 0237 { 0238 *(double*)ele = QtCurve::Str::convert(str, *(double*)data); 0239 return true; 0240 } 0241 0242 QTC_EXPORT double* 0243 qtcStrLoadFloatList(const char *str, char delim, char escape, size_t *nele, 0244 double *buff, size_t max_len, double def) 0245 { 0246 return (double*)qtcStrLoadList(str, delim, escape, sizeof(double), nele, 0247 buff, max_len, qtcStrListFloatLoader, &def); 0248 }