• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #4131

20 May 2025 07:22AM UTC coverage: 63.096% (+0.7%) from 62.384%
#4131

push

travis-ci

web-flow
docs(datain): add topic meta options docs in tmq (#31147)

157751 of 318088 branches covered (49.59%)

Branch coverage included in aggregate %.

243052 of 317143 relevant lines covered (76.64%)

18743283.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.71
/source/util/src/tutil.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#define _DEFAULT_SOURCE
17
#include "tutil.h"
18
#include "tlog.h"
19
#include "regex.h"
20

21
void *tmemmem(const char *haystack, int32_t hlen, const char *needle, int32_t nlen) {
6✔
22
  const char *limit;
23

24
  if (nlen == 0 || hlen < nlen) {
6!
25
    return NULL;
×
26
  }
27

28
  limit = haystack + hlen - nlen + 1;
6✔
29
  while ((haystack = (char *)memchr(haystack, needle[0], limit - haystack)) != NULL) {
309!
30
    if (memcmp(haystack, needle, nlen) == 0) {
309✔
31
      return (void *)haystack;
6✔
32
    }
33
    haystack++;
303✔
34
  }
35
  return NULL;
×
36
}
37

38
int32_t strdequote(char *z) {
29,672,166✔
39
  if (z == NULL) {
29,672,166!
40
    return 0;
×
41
  }
42

43
  int32_t quote = z[0];
29,672,166✔
44
  if (quote != '\'' && quote != '"' && quote != '`') {
29,672,166!
45
    return (int32_t)strlen(z);
29,473,677✔
46
  }
47

48
  int32_t i = 1, j = 0;
198,489✔
49

50
  while (z[i] != 0) {
1,457,422!
51
    if (z[i] == quote) {
1,473,841✔
52
      if (z[i + 1] == quote) {
214,908!
53
        z[j++] = (char)quote;
×
54
        i++;
×
55
      } else {
56
        z[j++] = 0;
214,908✔
57
        return (j - 1);
214,908✔
58
      }
59
    } else {
60
      z[j++] = z[i];
1,258,933✔
61
    }
62

63
    i++;
1,258,933✔
64
  }
65

66
  return j + 1;  // only one quote, do nothing
×
67
}
68

69
size_t strtrim(char *z) {
11,739✔
70
  int32_t i = 0;
11,739✔
71
  int32_t j = 0;
11,739✔
72

73
  int32_t delta = 0;
11,739✔
74
  while (isspace(z[j])) {
11,876✔
75
    ++j;
137✔
76
  }
77

78
  if (z[j] == 0) {
11,739✔
79
    z[0] = 0;
41✔
80
    return 0;
41✔
81
  }
82

83
  delta = j;
11,698✔
84

85
  int32_t stop = 0;
11,698✔
86
  while (z[j] != 0) {
111,987✔
87
    if (isspace(z[j]) && stop == 0) {
100,289✔
88
      stop = j;
524✔
89
    } else if (!isspace(z[j]) && stop != 0) {
99,765✔
90
      stop = 0;
408✔
91
    }
92

93
    z[i++] = z[j++];
100,289✔
94
  }
95

96
  if (stop > 0) {
11,698✔
97
    z[stop - delta] = 0;
116✔
98
    return (stop - delta);
116✔
99
  } else if (j != i) {
11,582✔
100
    z[i] = 0;
83✔
101
  }
102

103
  return i;
11,582✔
104
}
105

106
char **strsplit(char *z, const char *delim, int32_t *num) {
8,025✔
107
  *num = 0;
8,025✔
108
  int32_t size = 4;
8,025✔
109

110
  char **split = taosMemoryMalloc(POINTER_BYTES * size);
8,025!
111
  if (split == NULL) {
8,025!
112
    return NULL;
×
113
  }
114

115
  for (char *p = strsep(&z, delim); p != NULL; p = strsep(&z, delim)) {
16,359✔
116
    size_t len = strlen(p);
8,334✔
117
    if (len == 0) {
8,334✔
118
      continue;
9✔
119
    }
120

121
    split[(*num)++] = p;
8,325✔
122
    if ((*num) >= size) {
8,325✔
123
      size = (size << 1);
10✔
124
      split = taosMemoryRealloc(split, POINTER_BYTES * size);
10!
125
      if (split == NULL) {
10!
126
        return NULL;
×
127
      }
128
    }
129
  }
130

131
  return split;
8,025✔
132
}
133

134
char *strnchr(const char *haystack, char needle, int32_t len, bool skipquote) {
15,948,268✔
135
  for (int32_t i = 0; i < len; ++i) {
282,094,261✔
136
    // skip the needle in quote, jump to the end of quoted string
137
    if (skipquote && (haystack[i] == '\'' || haystack[i] == '"')) {
276,389,546!
138
      char quote = haystack[i++];
12,045✔
139
      while (i < len && haystack[i++] != quote)
72,292✔
140
        ;
141
      if (i >= len) {
12,045✔
142
        return NULL;
12,039✔
143
      }
144
    }
145

146
    if (haystack[i] == needle) {
276,377,507✔
147
      return (char *)&haystack[i];
10,231,514✔
148
    }
149
  }
150

151
  return NULL;
5,704,715✔
152
}
153

154
TdUcs4 *wcsnchr(const TdUcs4 *haystack, TdUcs4 needle, size_t len) {
11,897✔
155
  for (int32_t i = 0; i < len; ++i) {
31,841✔
156
    if (haystack[i] == needle) {
23,857✔
157
      return (TdUcs4 *)&haystack[i];
3,913✔
158
    }
159
  }
160

161
  return NULL;
7,984✔
162
}
163

164
char *strtolower(char *dst, const char *src) {
21,309,837✔
165
  int32_t esc = 0;
21,309,837✔
166
  char    quote = 0, *p = dst, c;
21,309,837✔
167

168
  for (c = *src++; c; c = *src++) {
843,640,288✔
169
    if (esc) {
822,330,451!
170
      esc = 0;
×
171
    } else if (quote) {
822,330,451✔
172
      if (c == '\\') {
99,371,658!
173
        esc = 1;
×
174
      } else if (c == quote) {
99,371,658✔
175
        quote = 0;
6,614,719✔
176
      }
177
    } else if (c >= 'A' && c <= 'Z') {
722,958,793✔
178
      c -= 'A' - 'a';
10,434,254✔
179
    } else if (c == '\'' || c == '"') {
712,524,539✔
180
      quote = c;
6,614,719✔
181
    }
182
    *p++ = c;
822,330,451✔
183
  }
184

185
  *p = 0;
21,309,837✔
186
  return dst;
21,309,837✔
187
}
188

189
char *strntolower(char *dst, const char *src, int32_t n) {
14,467,739✔
190
  int32_t esc = 0;
14,467,739✔
191
  char    quote = 0, *p = dst, c;
14,467,739✔
192

193
  if (n == 0) {
14,467,739✔
194
    *p = 0;
2,303✔
195
    return dst;
2,303✔
196
  }
197
  for (c = *src++; n-- > 0; c = *src++) {
2,147,483,647✔
198
    if (esc) {
2,147,483,647✔
199
      esc = 0;
5,802✔
200
    } else if (quote) {
2,147,483,647✔
201
      if (c == '\\') {
2,147,483,647✔
202
        esc = 1;
5,802✔
203
      } else if (c == quote) {
2,147,483,647✔
204
        quote = 0;
197,692,012✔
205
      }
206
    } else if (c >= 'A' && c <= 'Z') {
2,147,483,647✔
207
      c -= 'A' - 'a';
242,036,313✔
208
    } else if (c == '\'' || c == '"' || c == '`') {
2,147,483,647!
209
      quote = c;
198,046,834✔
210
    }
211
    *p++ = c;
2,147,483,647✔
212
  }
213

214
  *p = 0;
14,465,436✔
215
  return dst;
14,465,436✔
216
}
217

218
char *strntolower_s(char *dst, const char *src, int32_t n) {
×
219
  char *p = dst, c;
×
220
  if (n == 0) {
×
221
    return NULL;
×
222
  }
223

224
  while (n-- > 0) {
×
225
    c = *src;
×
226
    if (c >= 'A' && c <= 'Z') {
×
227
      c -= 'A' - 'a';
×
228
    }
229
    *p++ = c;
×
230
    src++;
×
231
  }
232

233
  return dst;
×
234
}
235

236
char *paGetToken(char *string, char **token, int32_t *tokenLen) {
37,999,899✔
237
  char quote = 0;
37,999,899✔
238

239
  while (*string != 0) {
61,007,442✔
240
    if (*string == ' ' || *string == '\t') {
56,193,434✔
241
      ++string;
23,007,543✔
242
    } else {
243
      break;
244
    }
245
  }
246

247
  if (*string == '@') {
37,999,899✔
248
    quote = 1;
8,845✔
249
    string++;
8,845✔
250
  }
251

252
  *token = string;
37,999,899✔
253

254
  while (*string != 0) {
134,909,230✔
255
    if (*string == '@' && quote) {
124,387,655✔
256
      //*string = 0;
257
      ++string;
8,845✔
258
      break;
8,845✔
259
    }
260

261
    if (*string == '#' || *string == '\n' || *string == '\r') {
124,378,810!
262
      *string = 0;
3,871,279✔
263
      break;
3,871,279✔
264
    }
265

266
    if ((*string == ' ' || *string == '\t') && !quote) {
120,507,531✔
267
      break;
268
    } else {
269
      ++string;
96,909,331✔
270
    }
271
  }
272

273
  *tokenLen = (int32_t)(string - *token);
37,999,899✔
274
  if (quote) {
37,999,899✔
275
    *tokenLen = *tokenLen - 1;
8,845✔
276
  }
277

278
  return string;
37,999,899✔
279
}
280

281
int64_t strnatoi(const char *num, int32_t len) {
10,678,584✔
282
  int64_t ret = 0, i, dig, base = 1;
10,678,584✔
283

284
  if (len > (int32_t)strlen(num)) {
10,678,584!
285
    len = (int32_t)strlen(num);
×
286
  }
287

288
  if ((len > 2) && (num[0] == '0') && ((num[1] == 'x') || (num[1] == 'X'))) {
10,678,584!
289
    for (i = len - 1; i >= 2; --i, base *= 16) {
×
290
      if (num[i] >= '0' && num[i] <= '9') {
×
291
        dig = (num[i] - '0');
×
292
      } else if (num[i] >= 'a' && num[i] <= 'f') {
×
293
        dig = num[i] - 'a' + 10;
×
294
      } else if (num[i] >= 'A' && num[i] <= 'F') {
×
295
        dig = num[i] - 'A' + 10;
×
296
      } else {
297
        return 0;
×
298
      }
299
      ret += dig * base;
×
300
    }
301
  } else {
302
    for (i = len - 1; i >= 0; --i, base *= 10) {
33,037,980✔
303
      if (num[i] >= '0' && num[i] <= '9') {
22,359,396!
304
        dig = (num[i] - '0');
22,359,396✔
305
      } else {
306
        return 0;
×
307
      }
308
      ret += dig * base;
22,359,396✔
309
    }
310
  }
311

312
  return ret;
10,678,584✔
313
}
314

315
char *strbetween(char *string, char *begin, char *end) {
×
316
  char *result = NULL;
×
317
  char *_begin = strstr(string, begin);
×
318
  if (_begin != NULL) {
×
319
    char   *_end = strstr(_begin + strlen(begin), end);
×
320
    int32_t size = (int32_t)(_end - _begin);
×
321
    if (_end != NULL && size > 0) {
×
322
      result = (char *)taosMemoryCalloc(1, size);
×
323
      if (!result) {
×
324
        return NULL;
×
325
      }
326
      memcpy(result, _begin + strlen(begin), size - +strlen(begin));
×
327
    }
328
  }
329
  return result;
×
330
}
331

332
static const char hexstr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
333

334
int32_t tintToHex(uint64_t val, char hex[]) {
17,964,527✔
335
  int32_t j = 0, k = 0;
17,964,527✔
336
  if (val == 0) {
17,964,527✔
337
    hex[j++] = hexstr[0];
10,596✔
338
    return j;
10,596✔
339
  }
340

341
  // ignore the initial 0
342
  while ((val & (((uint64_t)0xfL) << ((15 - k) * 4))) == 0) {
123,285,586✔
343
    k += 1;
105,331,655✔
344
  }
345

346
  for (j = 0; k < 16; ++k, ++j) {
199,858,378✔
347
    hex[j] = hexstr[(val & (((uint64_t)0xfL) << ((15 - k) * 4))) >> (15 - k) * 4];
181,904,447✔
348
  }
349

350
  return j;
17,953,931✔
351
}
352

353
int32_t titoa(uint64_t val, size_t radix, char str[]) {
198,262,786✔
354
  if (radix < 2 || radix > 16) {
198,262,786!
355
    return 0;
×
356
  }
357

358
  char        buf[65] = {0};
198,326,355✔
359

360
  int32_t  i = 0;
198,326,355✔
361
  uint64_t v = val;
198,326,355✔
362
  do {
363
    buf[i++] = hexstr[v % radix];
2,147,483,647✔
364
    v /= radix;
2,147,483,647✔
365
  } while (v > 0);
2,147,483,647✔
366

367
  // reverse order
368
  for (int32_t j = 0; j < i; ++j) {
2,147,483,647✔
369
    str[j] = buf[i - j - 1];
2,147,483,647✔
370
  }
371

372
  return i;
198,326,355✔
373
}
374

375
int32_t taosByteArrayToHexStr(char bytes[], int32_t len, char str[]) {
12,785✔
376
  int32_t i;
377

378
  for (i = 0; i < len; i++) {
217,319✔
379
    str[i * 2] = hexstr[((bytes[i] >> 4u) & 0xF)];
204,534✔
380
    str[(i * 2) + 1] = hexstr[(bytes[i]) & 0x0F];
204,534✔
381
  }
382

383
  return 0;
12,785✔
384
}
385

386
int32_t taosHexStrToByteArray(char hexstr[], char bytes[]) {
×
387
  int32_t len, i;
388
  char    ch;
389
  // char *by;
390

391
  len = (int32_t)strlen((char *)hexstr) / 2;
×
392

393
  for (i = 0; i < len; i++) {
×
394
    ch = hexstr[i * 2];
×
395
    if (ch >= '0' && ch <= '9')
×
396
      bytes[i] = (char)(ch - '0');
×
397
    else if (ch >= 'A' && ch <= 'F')
×
398
      bytes[i] = (char)(ch - 'A' + 10);
×
399
    else if (ch >= 'a' && ch <= 'f')
×
400
      bytes[i] = (char)(ch - 'a' + 10);
×
401
    else
402
      return -1;
×
403

404
    ch = hexstr[i * 2 + 1];
×
405
    if (ch >= '0' && ch <= '9')
×
406
      bytes[i] = (char)((bytes[i] << 4) + (ch - '0'));
×
407
    else if (ch >= 'A' && ch <= 'F')
×
408
      bytes[i] = (char)((bytes[i] << 4) + (ch - 'A' + 10));
×
409
    else if (ch >= 'a' && ch <= 'f')
×
410
      bytes[i] = (char)((bytes[i] << 4) + (ch - 'a' + 10));
×
411
    else
412
      return -1;
×
413
  }
414

415
  return 0;
×
416
}
417

418
size_t tstrncspn(const char *str, size_t size, const char *reject, size_t rsize) {
9,659,112✔
419
  if (rsize == 0 || rsize == 1) {
9,659,112!
420
    char *p = strnchr(str, reject[0], size, false);
×
421
    return (p == NULL) ? size : (p - str);
4✔
422
  }
423

424
  /* Use multiple small memsets to enable inlining on most targets.  */
425
  unsigned char  table[256];
426
  unsigned char *p = memset(table, 0, 64);
9,659,130✔
427
  memset(p + 64, 0, 64);
9,659,130✔
428
  memset(p + 128, 0, 64);
9,659,130✔
429
  memset(p + 192, 0, 64);
9,659,130✔
430

431
  unsigned char *s = (unsigned char *)reject;
9,659,130✔
432
  int32_t        index = 0;
9,659,130✔
433
  do {
434
    p[s[index++]] = 1;
19,318,372✔
435
  } while (index < rsize);
19,318,372✔
436

437
  s = (unsigned char *)str;
9,659,130✔
438
  int32_t times = size >> 2;
9,659,130✔
439
  if (times == 0) {
9,659,130✔
440
    for (int32_t i = 0; i < size; ++i) {
49,626✔
441
      if (p[s[i]]) {
42,181✔
442
        return i;
26,123✔
443
      }
444
    }
445

446
    return size;
7,445✔
447
  }
448

449
  index = 0;
9,625,562✔
450
  uint32_t c0, c1, c2, c3;
451
  for (int32_t i = 0; i < times; ++i, index += 4) {
9,675,768✔
452
    int32_t j = index;
9,650,589✔
453
    c0 = p[s[j]];
9,650,589✔
454
    c1 = p[s[j + 1]];
9,650,589✔
455
    c2 = p[s[j + 2]];
9,650,589✔
456
    c3 = p[s[j + 3]];
9,650,589✔
457

458
    if ((c0 | c1 | c2 | c3) != 0) {
9,650,589✔
459
      size_t count = i * 4;
9,600,383✔
460
      return (c0 | c1) != 0 ? count - c0 + 1 : count - c2 + 3;
9,600,383✔
461
    }
462
  }
463

464
  int32_t offset = times * 4;
25,179✔
465
  for (int32_t i = offset; i < size; ++i) {
67,202✔
466
    if (p[s[i]]) {
42,680✔
467
      return i;
657✔
468
    }
469
  }
470

471
  return size;
24,522✔
472
}
473

474
size_t twcsncspn(const TdUcs4 *wcs, size_t size, const TdUcs4 *reject, size_t rsize) {
4,262✔
475
  if (rsize == 0 || rsize == 1) {
4,262!
476
    TdUcs4 *p = wcsnchr(wcs, reject[0], size);
×
477
    return (p == NULL) ? size : (p - wcs);
×
478
  }
479

480
  size_t index = 0;
4,262✔
481
  while ((index < size) && (wcsnchr(reject, wcs[index], rsize) == NULL)) {
12,419✔
482
    ++index;
8,157✔
483
  }
484

485
  return index;
4,331✔
486
}
487

488
int32_t parseCfgReal(const char *str, float *out) {
92✔
489
  float val;
490
  char  *endPtr;
491
  SET_ERRNO(0);
92✔
492
  val = taosStr2Float(str, &endPtr);
92✔
493
  if (str == endPtr || ERRNO == ERANGE || isnan(val)) {
92!
494
    return terrno = TSDB_CODE_INVALID_CFG_VALUE;
2✔
495
  }
496
  while (isspace((unsigned char)*endPtr)) endPtr++;
92✔
497
  if (*endPtr != '\0') {
90✔
498
    return terrno = TSDB_CODE_INVALID_CFG_VALUE;
3✔
499
  }
500
  *out = val;
87✔
501
  return TSDB_CODE_SUCCESS;
87✔
502
}
503

504
bool tIsValidFileName(const char *fileName, const char *pattern) {
40✔
505
  const char *fileNamePattern = "^[a-zA-Z0-9_.-]+$";
40✔
506

507
  regex_t fileNameReg;
508

509
  if (pattern) fileNamePattern = pattern;
40✔
510

511
  if (regcomp(&fileNameReg, fileNamePattern, REG_EXTENDED) != 0) {
40!
512
    fprintf(stderr, "failed to compile file name pattern:%s\n", fileNamePattern);
×
513
    return false;
×
514
  }
515

516
  int32_t code = regexec(&fileNameReg, fileName, 0, NULL, 0);
40✔
517
  regfree(&fileNameReg);
40✔
518
  if (code != 0) {
40✔
519
    return false;
4✔
520
  }
521
  return true;
36✔
522
}
523

524
bool tIsValidFilePath(const char *filePath, const char *pattern) {
30✔
525
  const char *filePathPattern = "^[a-zA-Z0-9:/\\_.-]+$";
30✔
526
  return tIsValidFileName(filePath, pattern ? pattern : filePathPattern);
30!
527
}
528

529
bool taosIsBigChar(char c) {
3,901✔
530
  if (c >= 'A' && c <= 'Z') {
3,901✔
531
    return true;
491✔
532
  } else {
533
    return false;
3,410✔
534
  }
535
}
536

537
bool taosIsSmallChar(char c) {
3,410✔
538
  if (c >= 'a' && c <= 'z') {
3,410✔
539
    return true;
2,020✔
540
  } else {
541
    return false;
1,390✔
542
  }
543
}
544

545
bool taosIsNumberChar(char c) {
1,390✔
546
  if (c >= '0' && c <= '9') {
1,390✔
547
    return true;
982✔
548
  } else {
549
    return false;
408✔
550
  }
551
}
552

553
bool taosIsSpecialChar(char c) {
408✔
554
  switch (c) {
408✔
555
    case '!':
404✔
556
    case '@':
557
    case '#':
558
    case '$':
559
    case '%':
560
    case '^':
561
    case '&':
562
    case '*':
563
    case '(':
564
    case ')':
565
    case '-':
566
    case '_':
567
    case '+':
568
    case '=':
569
    case '[':
570
    case ']':
571
    case '{':
572
    case '}':
573
    case ':':
574
    case ';':
575
    case '>':
576
    case '<':
577
    case '?':
578
    case '|':
579
    case '~':
580
    case ',':
581
    case '.':
582
    return true;
404✔
583
    default:
4✔
584
    return false;
4✔
585
  }
586
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc