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

taosdata / TDengine / #3558

17 Dec 2024 06:05AM UTC coverage: 59.778% (+1.6%) from 58.204%
#3558

push

travis-ci

web-flow
Merge pull request #29179 from taosdata/merge/mainto3.0

merge: form main to 3.0 branch

132787 of 287595 branches covered (46.17%)

Branch coverage included in aggregate %.

104 of 191 new or added lines in 5 files covered. (54.45%)

6085 existing lines in 168 files now uncovered.

209348 of 284746 relevant lines covered (73.52%)

8164844.48 hits per line

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

66.45
/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) {
×
22
  const char *limit;
23

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

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

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

43
  int32_t quote = z[0];
26,872,294✔
44
  if (quote != '\'' && quote != '"' && quote != '`') {
26,872,294!
45
    return (int32_t)strlen(z);
26,876,506✔
46
  }
47

UNCOV
48
  int32_t i = 1, j = 0;
×
49

50
  while (z[i] != 0) {
66,400!
51
    if (z[i] == quote) {
83,657✔
52
      if (z[i + 1] == quote) {
13,045!
53
        z[j++] = (char)quote;
×
54
        i++;
×
55
      } else {
56
        z[j++] = 0;
13,045✔
57
        return (j - 1);
13,045✔
58
      }
59
    } else {
60
      z[j++] = z[i];
70,612✔
61
    }
62

63
    i++;
70,612✔
64
  }
65

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

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

73
  int32_t delta = 0;
6,457✔
74
  while (isspace(z[j])) {
6,466✔
75
    ++j;
9✔
76
  }
77

78
  if (z[j] == 0) {
6,457✔
79
    z[0] = 0;
25✔
80
    return 0;
25✔
81
  }
82

83
  delta = j;
6,432✔
84

85
  int32_t stop = 0;
6,432✔
86
  while (z[j] != 0) {
64,990✔
87
    if (isspace(z[j]) && stop == 0) {
58,558!
88
      stop = j;
67✔
89
    } else if (!isspace(z[j]) && stop != 0) {
58,491!
90
      stop = 0;
66✔
91
    }
92

93
    z[i++] = z[j++];
58,558✔
94
  }
95

96
  if (stop > 0) {
6,432✔
97
    z[stop - delta] = 0;
1✔
98
    return (stop - delta);
1✔
99
  } else if (j != i) {
6,431!
100
    z[i] = 0;
×
101
  }
102

103
  return i;
6,431✔
104
}
105

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

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

115
  for (char *p = strsep(&z, delim); p != NULL; p = strsep(&z, delim)) {
10,780✔
116
    size_t len = strlen(p);
5,390✔
117
    if (len == 0) {
5,390!
118
      continue;
×
119
    }
120

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

131
  return split;
5,390✔
132
}
133

134
char *strnchr(const char *haystack, char needle, int32_t len, bool skipquote) {
10,950,984✔
135
  for (int32_t i = 0; i < len; ++i) {
138,436,834✔
136
    // skip the needle in quote, jump to the end of quoted string
137
    if (skipquote && (haystack[i] == '\'' || haystack[i] == '"')) {
136,454,671✔
138
      char quote = haystack[i++];
12,000✔
139
      while (i < len && haystack[i++] != quote)
72,000!
140
        ;
141
      if (i >= len) {
12,000!
142
        return NULL;
12,000✔
143
      }
144
    }
145

146
    if (haystack[i] == needle) {
136,442,671✔
147
      return (char *)&haystack[i];
8,956,821✔
148
    }
149
  }
150

151
  return NULL;
1,982,163✔
152
}
153

154
TdUcs4 *wcsnchr(const TdUcs4 *haystack, TdUcs4 needle, size_t len) {
1,262✔
155
  for (int32_t i = 0; i < len; ++i) {
3,592✔
156
    if (haystack[i] == needle) {
2,427✔
157
      return (TdUcs4 *)&haystack[i];
97✔
158
    }
159
  }
160

161
  return NULL;
1,165✔
162
}
163

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

168
  for (c = *src++; c; c = *src++) {
16,314,402✔
169
    if (esc) {
16,116,142!
170
      esc = 0;
×
171
    } else if (quote) {
16,116,142✔
172
      if (c == '\\') {
7,737,431!
173
        esc = 1;
×
174
      } else if (c == quote) {
7,737,431✔
175
        quote = 0;
639,841✔
176
      }
177
    } else if (c >= 'A' && c <= 'Z') {
8,378,711✔
178
      c -= 'A' - 'a';
994,293✔
179
    } else if (c == '\'' || c == '"') {
7,384,418✔
180
      quote = c;
639,841✔
181
    }
182
    *p++ = c;
16,116,142✔
183
  }
184

185
  *p = 0;
198,260✔
186
  return dst;
198,260✔
187
}
188

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

193
  if (n == 0) {
11,537,270✔
194
    *p = 0;
739✔
195
    return dst;
739✔
196
  }
197
  for (c = *src++; n-- > 0; c = *src++) {
2,147,483,647✔
198
    if (esc) {
2,147,483,647✔
199
      esc = 0;
5,056✔
200
    } else if (quote) {
2,147,483,647✔
201
      if (c == '\\') {
2,147,483,647✔
202
        esc = 1;
5,056✔
203
      } else if (c == quote) {
2,147,483,647✔
204
        quote = 0;
119,479,980✔
205
      }
206
    } else if (c >= 'A' && c <= 'Z') {
2,147,483,647✔
207
      c -= 'A' - 'a';
193,685,824✔
208
    } else if (c == '\'' || c == '"' || c == '`') {
2,147,483,647!
209
      quote = c;
120,078,967✔
210
    }
211
    *p++ = c;
2,147,483,647✔
212
  }
213

214
  *p = 0;
11,536,531✔
215
  return dst;
11,536,531✔
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) {
31,196,982✔
237
  char quote = 0;
31,196,982✔
238

239
  while (*string != 0) {
54,030,596✔
240
    if (*string == ' ' || *string == '\t') {
51,798,755✔
241
      ++string;
22,833,614✔
242
    } else {
243
      break;
244
    }
245
  }
246

247
  if (*string == '@') {
31,196,982✔
248
    quote = 1;
8,808✔
249
    string++;
8,808✔
250
  }
251

252
  *token = string;
31,196,982✔
253

254
  while (*string != 0) {
125,504,635✔
255
    if (*string == '@' && quote) {
117,733,107✔
256
      //*string = 0;
257
      ++string;
8,808✔
258
      break;
8,808✔
259
    }
260

261
    if (*string == '#' || *string == '\n' || *string == '\r') {
117,724,299!
262
      *string = 0;
73,812✔
263
      break;
73,812✔
264
    }
265

266
    if ((*string == ' ' || *string == '\t') && !quote) {
117,650,487✔
267
      break;
268
    } else {
269
      ++string;
94,307,653✔
270
    }
271
  }
272

273
  *tokenLen = (int32_t)(string - *token);
31,196,982✔
274
  if (quote) {
31,196,982✔
275
    *tokenLen = *tokenLen - 1;
8,808✔
276
  }
277

278
  return string;
31,196,982✔
279
}
280

281
int64_t strnatoi(char *num, int32_t len) {
1,392,640✔
282
  int64_t ret = 0, i, dig, base = 1;
1,392,640✔
283

284
  if (len > (int32_t)strlen(num)) {
1,392,640!
285
    len = (int32_t)strlen(num);
×
286
  }
287

288
  if ((len > 2) && (num[0] == '0') && ((num[1] == 'x') || (num[1] == 'X'))) {
1,392,640!
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) {
4,501,154✔
303
      if (num[i] >= '0' && num[i] <= '9') {
3,108,514!
304
        dig = (num[i] - '0');
3,108,514✔
305
      } else {
306
        return 0;
×
307
      }
308
      ret += dig * base;
3,108,514✔
309
    }
310
  }
311

312
  return ret;
1,392,640✔
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
int32_t tintToHex(uint64_t val, char hex[]) {
4,737,640✔
333
  const char hexstr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
4,737,640✔
334

335
  int32_t j = 0, k = 0;
4,737,640✔
336
  if (val == 0) {
4,737,640✔
337
    hex[j++] = hexstr[0];
9,824✔
338
    return j;
9,824✔
339
  }
340

341
  // ignore the initial 0
342
  while ((val & (((uint64_t)0xfL) << ((15 - k) * 4))) == 0) {
33,128,352✔
343
    k += 1;
28,400,536✔
344
  }
345

346
  for (j = 0; k < 16; ++k, ++j) {
51,914,423✔
347
    hex[j] = hexstr[(val & (((uint64_t)0xfL) << ((15 - k) * 4))) >> (15 - k) * 4];
47,186,607✔
348
  }
349

350
  return j;
4,727,816✔
351
}
352

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

358
  const char *s = "0123456789abcdef";
181,263,889✔
359
  char        buf[65] = {0};
181,263,889✔
360

361
  int32_t  i = 0;
181,263,889✔
362
  uint64_t v = val;
181,263,889✔
363
  do {
364
    buf[i++] = s[v % radix];
2,064,741,948✔
365
    v /= radix;
2,064,741,948✔
366
  } while (v > 0);
2,064,741,948✔
367

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

373
  return i;
181,263,889✔
374
}
375

376
int32_t taosByteArrayToHexStr(char bytes[], int32_t len, char hexstr[]) {
×
377
  int32_t i;
378
  char    hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
×
379

380
  for (i = 0; i < len; i++) {
×
381
    hexstr[i * 2] = hexval[((bytes[i] >> 4u) & 0xF)];
×
382
    hexstr[(i * 2) + 1] = hexval[(bytes[i]) & 0x0F];
×
383
  }
384

385
  return 0;
×
386
}
387

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

393
  len = (int32_t)strlen((char *)hexstr) / 2;
×
394

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

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

417
  return 0;
×
418
}
419

420
size_t tstrncspn(const char *str, size_t size, const char *reject, size_t rsize) {
50,899✔
421
  if (rsize == 0 || rsize == 1) {
50,899!
422
    char *p = strnchr(str, reject[0], size, false);
×
423
    return (p == NULL) ? size : (p - str);
×
424
  }
425

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

433
  unsigned char *s = (unsigned char *)reject;
50,946✔
434
  int32_t        index = 0;
50,946✔
435
  do {
436
    p[s[index++]] = 1;
102,034✔
437
  } while (index < rsize);
102,034✔
438

439
  s = (unsigned char *)str;
50,946✔
440
  int32_t times = size >> 2;
50,946✔
441
  if (times == 0) {
50,946✔
442
    for (int32_t i = 0; i < size; ++i) {
34,032✔
443
      if (p[s[i]]) {
23,965✔
444
        return i;
2,434✔
445
      }
446
    }
447

448
    return size;
10,067✔
449
  }
450

451
  index = 0;
38,445✔
452
  uint32_t c0, c1, c2, c3;
453
  for (int32_t i = 0; i < times; ++i, index += 4) {
87,864✔
454
    int32_t j = index;
67,363✔
455
    c0 = p[s[j]];
67,363✔
456
    c1 = p[s[j + 1]];
67,363✔
457
    c2 = p[s[j + 2]];
67,363✔
458
    c3 = p[s[j + 3]];
67,363✔
459

460
    if ((c0 | c1 | c2 | c3) != 0) {
67,363✔
461
      size_t count = i * 4;
17,944✔
462
      return (c0 | c1) != 0 ? count - c0 + 1 : count - c2 + 3;
17,944✔
463
    }
464
  }
465

466
  int32_t offset = times * 4;
20,501✔
467
  for (int32_t i = offset; i < size; ++i) {
54,745✔
468
    if (p[s[i]]) {
34,651✔
469
      return i;
407✔
470
    }
471
  }
472

473
  return size;
20,094✔
474
}
475

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

482
  size_t index = 0;
452✔
483
  while ((index < size) && (wcsnchr(reject, wcs[index], rsize) == NULL)) {
1,617✔
484
    ++index;
1,165✔
485
  }
486

487
  return index;
452✔
488
}
489

490
int32_t parseCfgReal(const char *str, float *out) {
77✔
491
  float val;
492
  char  *endPtr;
493
  errno = 0;
77✔
494
  val = taosStr2Float(str, &endPtr);
77✔
495
  if (str == endPtr || errno == ERANGE || isnan(val)) {
77!
496
    return terrno = TSDB_CODE_INVALID_CFG_VALUE;
×
497
  }
498
  while (isspace((unsigned char)*endPtr)) endPtr++;
77!
499
  if (*endPtr != '\0') {
77!
500
    return terrno = TSDB_CODE_INVALID_CFG_VALUE;
×
501
  }
502
  *out = val;
77✔
503
  return TSDB_CODE_SUCCESS;
77✔
504
}
505

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

509
  regex_t fileNameReg;
510

511
  if (pattern) fileNamePattern = pattern;
3✔
512

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

518
  int32_t code = regexec(&fileNameReg, fileName, 0, NULL, 0);
3✔
519
  regfree(&fileNameReg);
3✔
520
  if (code != 0) {
3✔
521
    return false;
1✔
522
  }
523
  return true;
2✔
524
}
525

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

531
bool taosIsBigChar(char c) {
1,610✔
532
  if (c >= 'A' && c <= 'Z') {
1,610✔
533
    return true;
80✔
534
  } else {
535
    return false;
1,530✔
536
  }
537
}
538

539
bool taosIsSmallChar(char c) {
1,530✔
540
  if (c >= 'a' && c <= 'z') {
1,530✔
541
    return true;
960✔
542
  } else {
543
    return false;
570✔
544
  }
545
}
546

547
bool taosIsNumberChar(char c) {
570✔
548
  if (c >= '0' && c <= '9') {
570✔
549
    return true;
389✔
550
  } else {
551
    return false;
181✔
552
  }
553
}
554

555
bool taosIsSpecialChar(char c) {
181✔
556
  switch (c) {
181✔
557
    case '!':
179✔
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
    case ',':
583
    case '.':
584
    return true;
179✔
585
    default:
2✔
586
    return false;
2✔
587
  }
588
}
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