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

taosdata / TDengine / #4688

26 Aug 2025 02:05PM UTC coverage: 56.997% (-0.9%) from 57.894%
#4688

push

travis-ci

web-flow
fix: modify the prompt language of the taos-shell (#32758)

* fix: modify prompt language

* fix: add shell test case

* fix: modify comments

* fix: modify test case for TDengine TSDB

130660 of 292423 branches covered (44.68%)

Branch coverage included in aggregate %.

16 of 17 new or added lines in 2 files covered. (94.12%)

9459 existing lines in 157 files now uncovered.

198294 of 284715 relevant lines covered (69.65%)

4532552.29 hits per line

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

52.71
/source/os/src/osString.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 ALLOW_FORBID_FUNC
17
#define _DEFAULT_SOURCE
18
#include "os.h"
19

20
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
21
#include "iconv.h"
22
#endif
23

24
extern int wcwidth(wchar_t c);
25
extern int wcswidth(const wchar_t *s, size_t n);
26

27
char *tstrdup(const char *str) {
27,346,513✔
28
  if (str == NULL) {
27,346,513!
UNCOV
29
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
30
    return NULL;
×
31
  }
32
#ifdef WINDOWS
33
  return _strdup(str);
34
#else
35
  char *p = strdup(str);
27,346,513✔
36
  if (NULL == p) {
27,346,513!
37
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
38
  }
39
  return p;
27,346,513✔
40

41
#endif
42
}
43

44
#ifdef WINDOWS
45

46
// No errors are expected to occur
47
char *strsep(char **stringp, const char *delim) {
48
  if (stringp == NULL) {
49
    terrno = TSDB_CODE_INVALID_PARA;
50
    return NULL;
51
  }
52
  char       *s;
53
  const char *spanp;
54
  int32_t     c, sc;
55
  char       *tok;
56
  if ((s = *stringp) == NULL) return (NULL);
57
  if (delim == NULL) {
58
    terrno = TSDB_CODE_INVALID_PARA;
59
    return NULL;
60
  }
61
  for (tok = s;;) {
62
    c = *s++;
63
    spanp = delim;
64
    do {
65
      if ((sc = *spanp++) == c) {
66
        if (c == 0)
67
          s = NULL;
68
        else
69
          s[-1] = 0;
70
        *stringp = s;
71
        return (tok);
72
      }
73
    } while (sc != 0);
74
  }
75
  /* NOTREACHED */
76
}
77
/* Duplicate a string, up to at most size characters */
78
char *taosStrndupi(const char *s, int64_t size) {
79
  if (s == NULL) return NULL;
80
  size_t l;
81
  char  *s2;
82
  l = strlen(s);
83
  if (l > size) l = size;
84
  s2 = malloc(l + 1);
85
  if (s2) {
86
    tstrncpy(s2, s, l + 1);
87
    s2[l] = '\0';
88
  } else {
89
    terrno = TSDB_CODE_OUT_OF_MEMORY;
90
  }
91
  return s2;
92
}
93
/* Copy no more than N characters of SRC to DEST, returning the address of
94
   the terminating '\0' in DEST, if any, or else DEST + N.  */
95
char *stpncpy(char *dest, const char *src, int n) {
96
  if (dest == NULL || src == NULL) {
97
    terrno = TSDB_CODE_INVALID_PARA;
98
    return NULL;
99
  }
100
  size_t size = strnlen(src, n);
101
  memcpy(dest, src, size);
102
  dest += size;
103
  if (size == n) return dest;
104
  return memset(dest, '\0', n - size);
105
}
106
#elif defined(TD_ASTRA)
107
/* Copy no more than N characters of SRC to DEST, returning the address of
108
   the terminating '\0' in DEST, if any, or else DEST + N.  */
109
char *stpncpy(char *dest, const char *src, int n) {
110
  if (dest == NULL || src == NULL) { 
111
    terrno = TSDB_CODE_INVALID_PARA;
112
    return NULL;
113
  }
114
  if (n == 0) {
115
    return dest;
116
  }
117
  char *orig_dest = dest;
118
  const char *end = (const char *)memchr(src, '\0', n);
119
  size_t      len = (end != NULL) ? (size_t)(end - src) : n;
120
  memcpy(dest, src, len);
121
  if (len < n) {
122
    memset(dest + len, '\0', n - len);
123
  }
124
  return orig_dest + len;
125
}
126
char *taosStrndupi(const char *s, int64_t size) {
127
  if (s == NULL) {
128
    terrno = TSDB_CODE_INVALID_PARA;
129
    return NULL;
130
  }
131

132
  const char *end = (const char *)memchr(s, '\0', size);
133
  size_t      actual_len = (end != NULL) ? (size_t)(end - s) : (size_t)size;
134

135
  char *p = (char *)malloc(actual_len + 1);
136
  if (p == NULL) {
137
    terrno = TSDB_CODE_OUT_OF_MEMORY;
138
    return NULL;
139
  }
140

141
  memcpy(p, s, actual_len);
142
  p[actual_len] = '\0';
143

144
  return p;
145
}
146
#else
147
char *taosStrndupi(const char *s, int64_t size) {
2,221,443✔
148
  if (s == NULL) {
2,221,443!
UNCOV
149
    return NULL;
×
150
  }
151
  char *p = strndup(s, size);
2,221,443✔
152
  if (NULL == p) {
2,221,443!
153
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
154
  }
155
  return p;
2,221,443✔
156
}
157
#endif
158

159
char *tstrndup(const char *str, int64_t size) {
2✔
160
#if defined(WINDOWS) || defined(TD_ASTRA)
161
  return taosStrndupi(str, size);
162
#else
163
  char *p = strndup(str, size);
2✔
164
  if (str != NULL && NULL == p) {
2!
165
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
166
  }
167
  return p;
2✔
168

169
#endif
170
}
171

172
int32_t taosStr2int64(const char *str, int64_t *val) {
41,123,055✔
173
  if (str == NULL || val == NULL) {
41,123,055!
174
    return TSDB_CODE_INVALID_PARA;
×
175
  }
176
  SET_ERRNO(0);
41,123,846✔
177
  char   *endptr = NULL;
41,123,846✔
178
  int64_t ret = strtoll(str, &endptr, 10);
41,123,846✔
179
  if (ERRNO != 0) {
41,125,172!
180
    return TAOS_SYSTEM_ERROR(ERRNO);
×
181
  } else {
182
    if (endptr == str) {
41,125,172✔
183
      return TSDB_CODE_INVALID_PARA;
5✔
184
    }
185
    *val = ret;
41,125,167✔
186
    return 0;
41,125,167✔
187
  }
188
}
189

190
int32_t taosStr2int32(const char *str, int32_t *val) {
41,118,358✔
191
  OS_PARAM_CHECK(str);
41,118,358!
192
  OS_PARAM_CHECK(val);
41,118,358!
193
  int64_t tmp = 0;
41,118,358✔
194
  int32_t code = taosStr2int64(str, &tmp);
41,118,358✔
195
  if (code) {
41,119,079!
UNCOV
196
    return code;
×
197
  } else if (tmp > INT32_MAX || tmp < INT32_MIN) {
41,119,079!
198
    return TAOS_SYSTEM_ERROR(ERANGE);
×
199
  } else {
200
    *val = (int32_t)tmp;
41,120,076✔
201
    return 0;
41,120,076✔
202
  }
203
}
UNCOV
204
int32_t taosStr2int16(const char *str, int16_t *val) {
×
UNCOV
205
  OS_PARAM_CHECK(str);
×
UNCOV
206
  OS_PARAM_CHECK(val);
×
UNCOV
207
  int64_t tmp = 0;
×
UNCOV
208
  int32_t code = taosStr2int64(str, &tmp);
×
UNCOV
209
  if (code) {
×
UNCOV
210
    return code;
×
UNCOV
211
  } else if (tmp > INT16_MAX || tmp < INT16_MIN) {
×
UNCOV
212
    return TAOS_SYSTEM_ERROR(ERANGE);
×
213
  } else {
UNCOV
214
    *val = (int16_t)tmp;
×
UNCOV
215
    return 0;
×
216
  }
217
}
218

219
int32_t taosStr2int8(const char *str, int8_t *val) {
183✔
220
  OS_PARAM_CHECK(str);
183!
221
  OS_PARAM_CHECK(val);
183!
222
  int64_t tmp = 0;
183✔
223
  int32_t code = taosStr2int64(str, &tmp);
183✔
224
  if (code) {
183✔
225
    return code;
1✔
226
  } else if (tmp > INT8_MAX || tmp < INT8_MIN) {
182!
UNCOV
227
    return TAOS_SYSTEM_ERROR(ERANGE);
×
228
  } else {
229
    *val = (int8_t)tmp;
182✔
230
    return 0;
182✔
231
  }
232
}
233

UNCOV
234
int32_t taosStr2Uint64(const char *str, uint64_t *val) {
×
UNCOV
235
  if (str == NULL || val == NULL) {
×
UNCOV
236
    return TSDB_CODE_INVALID_PARA;
×
237
  }
UNCOV
238
  char *endptr = NULL;
×
UNCOV
239
  SET_ERRNO(0);
×
UNCOV
240
  uint64_t ret = strtoull(str, &endptr, 10);
×
241

UNCOV
242
  if (ERRNO != 0) {
×
243
    return TAOS_SYSTEM_ERROR(ERRNO);
×
244
  } else {
UNCOV
245
    if (endptr == str) {
×
UNCOV
246
      return TSDB_CODE_INVALID_PARA;
×
247
    }
UNCOV
248
    *val = ret;
×
UNCOV
249
    return 0;
×
250
  }
251
}
252

UNCOV
253
int32_t taosStr2Uint32(const char *str, uint32_t *val) {
×
UNCOV
254
  OS_PARAM_CHECK(str);
×
UNCOV
255
  OS_PARAM_CHECK(val);
×
UNCOV
256
  uint64_t tmp = 0;
×
UNCOV
257
  int32_t  code = taosStr2Uint64(str, &tmp);
×
UNCOV
258
  if (code) {
×
UNCOV
259
    return code;
×
UNCOV
260
  } else if (tmp > UINT32_MAX) {
×
UNCOV
261
    return TAOS_SYSTEM_ERROR(ERANGE);
×
262
  } else {
UNCOV
263
    *val = (int32_t)tmp;
×
UNCOV
264
    return 0;
×
265
  }
266
}
267

UNCOV
268
int32_t taosStr2Uint16(const char *str, uint16_t *val) {
×
UNCOV
269
  OS_PARAM_CHECK(str);
×
UNCOV
270
  OS_PARAM_CHECK(val);
×
UNCOV
271
  uint64_t tmp = 0;
×
UNCOV
272
  int32_t  code = taosStr2Uint64(str, &tmp);
×
UNCOV
273
  if (code) {
×
UNCOV
274
    return code;
×
UNCOV
275
  } else if (tmp > UINT16_MAX) {
×
UNCOV
276
    return TAOS_SYSTEM_ERROR(ERANGE);
×
277
  } else {
UNCOV
278
    *val = (int16_t)tmp;
×
UNCOV
279
    return 0;
×
280
  }
281
}
282

UNCOV
283
int32_t taosStr2Uint8(const char *str, uint8_t *val) {
×
UNCOV
284
  OS_PARAM_CHECK(str);
×
UNCOV
285
  OS_PARAM_CHECK(val);
×
UNCOV
286
  uint64_t tmp = 0;
×
UNCOV
287
  int32_t  code = taosStr2Uint64(str, &tmp);
×
UNCOV
288
  if (code) {
×
UNCOV
289
    return code;
×
UNCOV
290
  } else if (tmp > UINT8_MAX) {
×
UNCOV
291
    return TAOS_SYSTEM_ERROR(ERANGE);
×
292
  } else {
UNCOV
293
    *val = (int8_t)tmp;
×
UNCOV
294
    return 0;
×
295
  }
296
}
297

298
int32_t taosUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes) {
68,309,175✔
299
  if ((f1_ucs4 == NULL || f2_ucs4 == NULL)) {
68,309,175!
300
    return TSDB_CODE_INVALID_PARA;
×
301
  }
302
  for (int32_t i = 0; i < bytes; i += sizeof(TdUcs4)) {
446,760,196✔
303
    int32_t f1 = *(int32_t *)((char *)f1_ucs4 + i);
398,228,332✔
304
    int32_t f2 = *(int32_t *)((char *)f2_ucs4 + i);
398,228,332✔
305

306
    if ((f1 == 0 && f2 != 0) || (f1 != 0 && f2 == 0)) {
398,228,332!
UNCOV
307
      return f1 - f2;
×
308
    } else if (f1 == 0 && f2 == 0) {
398,228,332!
UNCOV
309
      return 0;
×
310
    }
311

312
    if (f1 != f2) {
398,228,332✔
313
      return f1 - f2;
19,826,906✔
314
    }
315
  }
316

317
  return 0;
48,531,864✔
318

319
  //#if 0
320
  //  int32_t ucs4_max_len = bytes + 4;
321
  //  char *f1_mbs = taosMemoryCalloc(bytes, 1);
322
  //  char *f2_mbs = taosMemoryCalloc(bytes, 1);
323
  //  if (taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs) < 0) {
324
  //    return -1;
325
  //  }
326
  //  if (taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs) < 0) {
327
  //    return -1;
328
  //  }
329
  //  int32_t ret = strcmp(f1_mbs, f2_mbs);
330
  //  taosMemoryFree(f1_mbs);
331
  //  taosMemoryFree(f2_mbs);
332
  //  return ret;
333
  //#endif
334
}
335

336
#if 0
337
int32_t tasoUcs4Copy(TdUcs4 *target_ucs4, TdUcs4 *source_ucs4, int32_t len_ucs4) {
338
  if (target_ucs4 == NULL || source_ucs4 == NULL || len_ucs4 <= 0) {
339
    return TSDB_CODE_INVALID_PARA;
340
  }
341
#ifndef TD_ASTRA
342
  if (taosMemorySize(target_ucs4) < len_ucs4 * sizeof(TdUcs4)) {
343
    terrno = TSDB_CODE_INVALID_PARA;
344
    return terrno;
345
  }
346

347
  (void)memcpy(target_ucs4, source_ucs4, len_ucs4 * sizeof(TdUcs4));
348

349
  return TSDB_CODE_SUCCESS;
350
#else
351
  return TSDB_CODE_APP_ERROR;
352
#endif
353
}
354
#endif 
355

356
iconv_t taosAcquireConv(int32_t *idx, ConvType type, void* charsetCxt) {
28,851,768✔
357
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
358
  if(idx == NULL) {
28,851,768!
UNCOV
359
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
360
    return (iconv_t)NULL;
×
361
  }
362
  if (charsetCxt == NULL){
28,851,768!
363
    charsetCxt = tsCharsetCxt;
28,865,370✔
364
  }
365
  SConvInfo *info = (SConvInfo *)charsetCxt;
28,851,768✔
366
  if (info == NULL) {
28,851,768!
UNCOV
367
    *idx = -1;
×
UNCOV
368
    if (type == M2C) {
×
UNCOV
369
      iconv_t c = iconv_open(DEFAULT_UNICODE_ENCODEC, "UTF-8");
×
UNCOV
370
      if ((iconv_t)-1 == c) {
×
371
        terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
372
      }
UNCOV
373
      return c;
×
374
    } else {
UNCOV
375
      iconv_t c = iconv_open("UTF-8", DEFAULT_UNICODE_ENCODEC);
×
UNCOV
376
      if ((iconv_t)-1 == c) {
×
377
        terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
378
      }
UNCOV
379
      return c;
×
380
    }
381
  }
382

383
  while (true) {
×
384
    int32_t used = atomic_add_fetch_32(&info->convUsed[type], 1);
28,851,768✔
385
    if (used > info->gConvMaxNum[type]) {
28,947,563!
386
      (void)atomic_sub_fetch_32(&info->convUsed[type], 1);
×
387
      (void)sched_yield();
×
388
      continue;
×
389
    }
390

391
    break;
28,961,710✔
392
  }
393

394
  int32_t startId = taosGetSelfPthreadId() % info->gConvMaxNum[type];
28,961,710✔
395
  while (true) {
33,697✔
396
    if (info->gConv[type][startId].inUse) {
28,956,475✔
397
      startId = (startId + 1) % info->gConvMaxNum[type];
14,577✔
398
      continue;
14,577✔
399
    }
400

401
    int8_t old = atomic_val_compare_exchange_8(&info->gConv[type][startId].inUse, 0, 1);
28,941,898✔
402
    if (0 == old) {
28,957,738✔
403
      break;
28,938,618✔
404
    }
405
  }
406

407
  *idx = startId;
28,938,618✔
408
  if ((iconv_t)0 == info->gConv[type][startId].conv) {
28,938,618!
409
    return (iconv_t)-1;
×
410
  } else {
411
    return info->gConv[type][startId].conv;
28,938,618✔
412
  }
413
#else
414
  terrno = TSDB_CODE_APP_ERROR;
415
  return (iconv_t)-1;
416
#endif
417
}
418

419
void taosReleaseConv(int32_t idx, iconv_t conv, ConvType type, void *charsetCxt) {
28,889,961✔
420
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
421
  if (idx < 0) {
28,889,961!
UNCOV
422
    (void)iconv_close(conv);
×
UNCOV
423
    return;
×
424
  }
425

426
  if (charsetCxt == NULL) {
28,889,961!
427
    charsetCxt = tsCharsetCxt;
28,900,245✔
428
  }
429
  SConvInfo *info = (SConvInfo *)charsetCxt;
28,889,961✔
430

431
  atomic_store_8(&info->gConv[type][idx].inUse, 0);
28,889,961✔
432
  (void)atomic_sub_fetch_32(&info->convUsed[type], 1);
28,962,512✔
433
#endif
434
}
435

436
bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len, void* charsetCxt) {
23,403,616✔
437
  if (ucs4_max_len == 0) {
23,403,616✔
438
    return true;
355,502✔
439
  }
440
  if (ucs4_max_len < 0 || mbs == NULL || ucs4 == NULL) {
23,048,114!
441
    terrno = TSDB_CODE_INVALID_PARA;
×
442
    return false;
×
443
  }
444
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
445
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
446
  terrno = TSDB_CODE_APP_ERROR;
447
  return false;
448
#else
449
  (void)memset(ucs4, 0, ucs4_max_len);
23,069,736✔
450

451
  int32_t idx = -1;
23,069,736✔
452
  iconv_t conv = taosAcquireConv(&idx, M2C, charsetCxt);
23,069,736✔
453
  if ((iconv_t)-1 == conv) {
23,176,807!
454
    return false;
×
455
  }
456

457
  size_t ucs4_input_len = mbsLength;
23,176,807✔
458
  size_t outLeft = ucs4_max_len;
23,176,807✔
459
  if (iconv(conv, (char **)&mbs, &ucs4_input_len, (char **)&ucs4, &outLeft) == -1) {
23,176,807✔
460
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
2✔
461
    taosReleaseConv(idx, conv, M2C, charsetCxt);
2✔
462
    return false;
1,322✔
463
  }
464

465
  taosReleaseConv(idx, conv, M2C, charsetCxt);
23,163,127✔
466
  if (len != NULL) {
23,207,941!
467
    *len = (int32_t)(ucs4_max_len - outLeft);
23,209,367✔
468
    if (*len < 0) {
23,209,367!
469
      // can not happen
470
      terrno = TSDB_CODE_APP_ERROR;
×
471
      return false;
×
472
    }
473
  }
474

475
  return true;
23,207,941✔
476
#endif
477
}
478

479
// if success, return the number of bytes written to mbs ( >= 0)
480
// otherwise return error code ( < 0)
481
int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs, void* charsetCxt) {
5,725,857✔
482
  if (ucs4_max_len == 0) {
5,725,857✔
483
    return 0;
112✔
484
  }
485
  if (ucs4_max_len < 0 || ucs4 == NULL || mbs == NULL) {
5,725,745!
486
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
487
    return terrno;
×
488
  }
489
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
490
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
491
  terrno = TSDB_CODE_APP_ERROR;
492
  return terrno;
493
#else
494

495
  int32_t idx = -1;
5,726,000✔
496
  int32_t code = 0;
5,726,000✔
497
  iconv_t conv = taosAcquireConv(&idx, C2M, charsetCxt);
5,726,000✔
498
  if ((iconv_t)-1 == conv) {
5,728,699!
499
    return terrno;
×
500
  }
501

502
  size_t ucs4_input_len = ucs4_max_len;
5,728,699✔
503
  size_t outLen = ucs4_max_len;
5,728,699✔
504
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
5,728,699!
505
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
506
    taosReleaseConv(idx, conv, C2M, charsetCxt);
×
507
    terrno = code;
×
508
    return code;
65✔
509
  }
510

511
  taosReleaseConv(idx, conv, C2M, charsetCxt);
5,728,903✔
512

513
  return (int32_t)(ucs4_max_len - outLen);
5,730,034✔
514
#endif
515
}
516

517
// if success, return the number of bytes written to mbs ( >= 0)
518
// otherwise return error code ( < 0)
519
int32_t taosUcs4ToMbsEx(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs, iconv_t conv) {
356,379✔
520
  if (ucs4_max_len == 0) {
356,379✔
521
    return 0;
2,660✔
522
  }
523
  if (ucs4_max_len < 0 || ucs4 == NULL || mbs == NULL) {
353,719!
524
    terrno = TSDB_CODE_INVALID_PARA;
×
525
    return terrno;
×
526
  }
527
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
528
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
529
  terrno = TSDB_CODE_APP_ERROR;
530
  return terrno;
531
#else
532

533
  size_t ucs4_input_len = ucs4_max_len;
353,719✔
534
  size_t outLen = ucs4_max_len;
353,719✔
535
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
353,719!
536
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
537
    return terrno;
×
538
  }
539

540
  return (int32_t)(ucs4_max_len - outLen);
353,719✔
541
#endif
542
}
543

544
bool taosValidateEncodec(const char *encodec) {
7,010✔
545
  if (encodec == NULL) {
7,010!
UNCOV
546
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
547
    return false;
×
548
  }
549
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
550
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
551
  terrno = TSDB_CODE_APP_ERROR;
552
  return false;
553
#else
554
  iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC);
7,010✔
555
  if (cd == (iconv_t)(-1)) {
7,010✔
556
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1✔
557
    return false;
1✔
558
  }
559

560
  (void)iconv_close(cd);
7,009✔
561
  return true;
7,009✔
562
#endif
563
}
564

UNCOV
565
int32_t taosUcs4len(TdUcs4 *ucs4) {
×
UNCOV
566
  TdUcs4 *wstr = (TdUcs4 *)ucs4;
×
UNCOV
567
  if (NULL == wstr) {
×
UNCOV
568
    return 0;
×
569
  }
570

UNCOV
571
  int32_t n = 0;
×
572
  while (1) {
UNCOV
573
    if (0 == *wstr++) {
×
UNCOV
574
      break;
×
575
    }
UNCOV
576
    n++;
×
577
  }
578

UNCOV
579
  return n;
×
580
}
581

582
// dst buffer size should be at least 2*len + 1
UNCOV
583
int32_t taosHexEncode(const unsigned char *src, char *dst, int32_t len, int32_t bufSize) {
×
UNCOV
584
  if (!dst || !src || bufSize <= 0) {
×
UNCOV
585
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
586
    return terrno;
×
587
  }
588

UNCOV
589
  for (int32_t i = 0; i < len; ++i) {
×
UNCOV
590
    (void)snprintf(dst + i * 2, bufSize - i * 2, "%02x", src[i]);
×
591
  }
592

UNCOV
593
  return 0;
×
594
}
595

UNCOV
596
int32_t taosHexDecode(const char *src, char *dst, int32_t len) {
×
UNCOV
597
  if (!src || !dst || len <= 0) {
×
UNCOV
598
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
599
    return terrno;
×
600
  }
601

602
  uint8_t hn, ln, out;
UNCOV
603
  for (int i = 0, j = 0; i < len * 2; i += 2, ++j) {
×
UNCOV
604
    hn = src[i] > '9' ? src[i] - 'a' + 10 : src[i] - '0';
×
UNCOV
605
    ln = src[i + 1] > '9' ? src[i + 1] - 'a' + 10 : src[i + 1] - '0';
×
606

UNCOV
607
    out = (hn << 4) | ln;
×
UNCOV
608
    (void)memcpy(dst + j, &out, 1);
×
609
  }
610

UNCOV
611
  return 0;
×
612
}
613

614
#ifdef TD_ASTRA
615
#include <wchar.h>
616
#include <stdbool.h>
617
#include <stdint.h>
618

619
typedef struct {
620
    uint32_t start;
621
    uint32_t end;
622
} SUnicodeRange;
623

624
static const SUnicodeRange __eaw_ranges[] = {
625
    {0x1100, 0x115F},   {0x2329, 0x232A}, {0x2E80, 0x303E}, {0x3040, 0xA4CF},
626
    {0xAC00, 0xD7AF},   {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0x20000, 0x2FFFD},
627
    {0x30000, 0x3FFFD}, {0xFF00, 0xFFEF}, {0xA000, 0xA48F}, {0x13A0, 0x13FF}
628
};
629

630
static const int __n_eaw_ranges = sizeof(__eaw_ranges) / sizeof(__eaw_ranges[0]);
631

632
static bool isEawWideChar(wchar_t code_point) {
633
    int low = 0;
634
    int high = __n_eaw_ranges - 1;
635

636
    while (low <= high) {
637
        int mid = (low + high) / 2;
638
        if (code_point < __eaw_ranges[mid].start) {
639
            high = mid - 1;
640
        } else if (code_point > __eaw_ranges[mid].end) {
641
            low = mid + 1;
642
        } else {
643
            return true;
644
        }
645
    }
646
    return false;
647
}
648

649
int wcwidth(wchar_t c) {
650
    if (c < 0x20 || (c >= 0x7F && c <= 0x9F)) {
651
        return 0;
652
    }
653
    if (isEawWideChar(c)) {
654
        return 2;
655
    }
656
    if (c >= 0x0300 && c <= 0x036F) {
657
        return 0;
658
    }
659
    return 1;
660
}
661

662
#endif
663

664
int32_t taosWcharWidth(TdWchar wchar) { return wcwidth(wchar); }
2,809,493✔
665

UNCOV
666
int32_t taosWcharsWidth(TdWchar *pWchar, int32_t size) {
×
UNCOV
667
  if (pWchar == NULL || size <= 0) {
×
UNCOV
668
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
669
    return terrno;
×
670
  }
671
#ifndef TD_ASTRA
UNCOV
672
  return wcswidth(pWchar, size);
×
673
#else
674
  int32_t width = 0;
675
  for (int32_t i = 0; i < size; ++i) {
676
    width += wcwidth(pWchar[i]);
677
  }
678
  return width;
679
#endif
680
}
681

682
int32_t taosMbToWchar(TdWchar *pWchar, const char *pStr, int32_t size) {
2,809,456✔
683
  if (pWchar == NULL || pStr == NULL || size <= 0) {
2,809,456!
UNCOV
684
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
685
    return terrno;
×
686
  }
687
#ifndef TD_ASTRA
688
  return mbtowc(pWchar, pStr, size);
2,809,456✔
689
#else
690
  return mbrtowc(pWchar, &pStr, size, NULL);
691
#endif
692
}
693

694
#ifdef TD_ASTRA
695
size_t mbstowcs(wchar_t *dest, const char *src, size_t n) {
696
  if (src == NULL) {
697
    return 0;
698
  }
699

700
  size_t count = 0;
701
  int    result;
702
  while (*src && count < n) {
703
    result = mbrtowc(dest, src, MB_CUR_MAX, NULL);
704
    if (result == -1 || result == 0) {
705
      return -1;
706
    }
707
    src += result;
708
    dest++;
709
    count++;
710
  }
711

712
  if (count < n) {
713
    *dest = L'\0';
714
  }
715
  return count;
716
}
717
#endif
718

UNCOV
719
int32_t taosMbsToWchars(TdWchar *pWchars, const char *pStrs, int32_t size) {
×
UNCOV
720
  if (pWchars == NULL || pStrs == NULL || size <= 0) {
×
UNCOV
721
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
722
    return terrno;
×
723
  }
UNCOV
724
  return mbstowcs(pWchars, pStrs, size);
×
725
}
726

UNCOV
727
int32_t taosWcharToMb(char *pStr, TdWchar wchar) {
×
UNCOV
728
  OS_PARAM_CHECK(pStr);
×
729
#ifndef TD_ASTRA
UNCOV
730
  return wctomb(pStr, wchar);
×
731
#else
732
  return wcrtomb(pStr, wchar, NULL);
733
#endif
734
}
735

UNCOV
736
char *taosStrCaseStr(const char *str, const char *pattern) {
×
UNCOV
737
  if (str == NULL) {
×
UNCOV
738
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
739
    return NULL;
×
740
  }
UNCOV
741
  if (!pattern || !*pattern) return (char *)str;
×
742

743
  size_t i;
744
  for (; *str; str++) {
×
745
    if (toupper(*str) == toupper(*pattern)) {
×
746
      for (i = 1;; i++) {
×
747
        if (!pattern[i]) return (char *)str;
×
748
        if (toupper(str[i]) != toupper(pattern[i])) break;
×
749
      }
750
    }
751
  }
752
  return NULL;
×
753
}
754

755
int64_t taosStr2Int64(const char *str, char **pEnd, int32_t radix) {
302,432,700✔
756
  if (str == NULL) {
302,432,700!
UNCOV
757
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
758
    return 0;
×
759
  }
760
  int64_t tmp = strtoll(str, pEnd, radix);
302,432,700✔
761
#if defined(DARWIN) || defined(_ALPINE)
762
  if (ERRNO == EINVAL) SET_ERRNO(0);
763
#endif
764
  return tmp;
326,568,909✔
765
}
766

767
uint64_t taosStr2UInt64(const char *str, char **pEnd, int32_t radix) {
52,432,982✔
768
  if (str == NULL) {
52,432,982!
UNCOV
769
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
770
    return 0;
×
771
  }
772
  uint64_t tmp = strtoull(str, pEnd, radix);
52,432,982✔
773
#if defined(DARWIN) || defined(_ALPINE)
774
  if (ERRNO == EINVAL) SET_ERRNO(0);
775
#endif
776
  return tmp;
52,714,677✔
777
}
778

779
int32_t taosStr2Int32(const char *str, char **pEnd, int32_t radix) {
1,811,712✔
780
  if (str == NULL) {
1,811,712!
UNCOV
781
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
782
    return 0;
×
783
  }
784
  int32_t tmp = strtol(str, pEnd, radix);
1,811,712✔
785
#if defined(DARWIN) || defined(_ALPINE)
786
  if (ERRNO == EINVAL) SET_ERRNO(0);
787
#endif
788
  return tmp;
1,812,375✔
789
}
790

791
uint32_t taosStr2UInt32(const char *str, char **pEnd, int32_t radix) {
2,511✔
792
  if (str == NULL) {
2,511!
UNCOV
793
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
794
    return 0;
×
795
  }
796
  uint32_t tmp = strtol(str, pEnd, radix);
2,511✔
797
#if defined(DARWIN) || defined(_ALPINE)
798
  if (ERRNO == EINVAL) SET_ERRNO(0);
799
#endif
800
  return tmp;
2,511✔
801
}
802

803
int16_t taosStr2Int16(const char *str, char **pEnd, int32_t radix) {
4,829✔
804
  if (str == NULL) {
4,829!
UNCOV
805
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
806
    return 0;
×
807
  }
808
  int32_t tmp = strtol(str, pEnd, radix);
4,829✔
809
#if defined(DARWIN) || defined(_ALPINE)
810
  if (ERRNO == EINVAL) SET_ERRNO(0);
811
#endif
812
  return (int16_t)tmp;
4,829✔
813
}
814

815
uint16_t taosStr2UInt16(const char *str, char **pEnd, int32_t radix) {
35,948✔
816
  if (str == NULL) {
35,948!
UNCOV
817
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
818
    return 0;
×
819
  }
820
  uint32_t tmp = strtoul(str, pEnd, radix);
35,948✔
821
#if defined(DARWIN) || defined(_ALPINE)
822
  if (ERRNO == EINVAL) SET_ERRNO(0);
823
#endif
824
  return (uint16_t)tmp;
35,962✔
825
}
826

827
int8_t taosStr2Int8(const char *str, char **pEnd, int32_t radix) {
9,590✔
828
  if (str == NULL) {
9,590!
UNCOV
829
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
830
    return 0;
×
831
  }
832
  int32_t tmp = strtol(str, pEnd, radix);
9,590✔
833
  return tmp;
9,590✔
834
}
835

836
uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix) {
667✔
837
  if (str == NULL) {
667!
UNCOV
838
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
839
    return 0;
×
840
  }
841
  uint32_t tmp = strtoul(str, pEnd, radix);
667✔
842
#if defined(DARWIN) || defined(_ALPINE)
843
  if (ERRNO == EINVAL) SET_ERRNO(0);
844
#endif
845
  return tmp;
665✔
846
}
847

848
double taosStr2Double(const char *str, char **pEnd) {
44,726,462✔
849
  if (str == NULL) {
44,726,462!
UNCOV
850
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
851
    return 0;
×
852
  }
853
  double tmp = strtod(str, pEnd);
44,726,462✔
854
  return tmp;
45,398,936✔
855
}
856

857
float taosStr2Float(const char *str, char **pEnd) {
49,154✔
858
  if (str == NULL) {
49,154!
UNCOV
859
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
860
    return 0;
×
861
  }
862
  float tmp = strtof(str, pEnd);
49,154✔
863
  return tmp;
49,154✔
864
}
865

866
#define HEX_PREFIX_LEN 2  // \x
867
bool isHex(const char *z, uint32_t n) {
2,381✔
868
  if (n < HEX_PREFIX_LEN) return false;
2,381✔
869
  if (z[0] == '\\' && z[1] == 'x') return true;
1,735✔
870
  return false;
1,693✔
871
}
872

873
bool isValidateHex(const char *z, uint32_t n) {
42✔
874
  if (!z) {
42!
UNCOV
875
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
876
    return false;
×
877
  }
878
  if ((n & 1) != 0) return false;
42✔
879
  for (size_t i = HEX_PREFIX_LEN; i < n; i++) {
131,291✔
880
    if (isxdigit(z[i]) == 0) {
131,252!
881
      return false;
×
882
    }
883
  }
884
  return true;
39✔
885
}
886

887
int32_t taosHex2Ascii(const char *z, uint32_t n, void **data, uint32_t *size) {
39✔
888
  OS_PARAM_CHECK(z);
39!
889
  OS_PARAM_CHECK(data);
39!
890
  OS_PARAM_CHECK(size);
39!
891
  n -= HEX_PREFIX_LEN;  // remove 0x
39✔
892
  z += HEX_PREFIX_LEN;
39✔
893
  *size = n / HEX_PREFIX_LEN;
39✔
894
  if (*size == 0) {
39✔
895
    if (!(*data = taosStrdup(""))) {
3!
896
      return terrno;
×
897
    }
898
    return 0;
3✔
899
  }
900

901
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size, 1);
36!
902
  if (tmp == NULL) {
36!
903
    return terrno;
×
904
  }
905

906
  int8_t   num = 0;
36✔
907
  uint8_t *byte = tmp + *size - 1;
36✔
908

909
  for (int i = n - 1; i >= 0; i--) {
131,288✔
910
    if (z[i] >= 'a') {
131,252✔
911
      *byte |= ((uint8_t)(10 + (z[i] - 'a')) << (num * 4));
24✔
912
    } else if (z[i] >= 'A') {
131,228✔
913
      *byte |= ((uint8_t)(10 + (z[i] - 'A')) << (num * 4));
13✔
914
    } else {
915
      *byte |= ((uint8_t)(z[i] - '0') << (num * 4));
131,215✔
916
    }
917
    if (num == 1) {
131,252✔
918
      byte--;
65,626✔
919
      num = 0;
65,626✔
920
    } else {
921
      num++;
65,626✔
922
    }
923
  }
924
  *data = tmp;
36✔
925

926
  return 0;
36✔
927
}
928

929
// int32_t taosBin2Ascii(const char *z, uint32_t n, void** data, uint32_t* size){
930
//
931
//   for (i = 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) {
932
//   }
933
//
934
//   n -= 2;   // remove 0b
935
//   z += 2;
936
//   *size = n%8 == 0 ? n/8 : n/8 + 1;
937
//   uint8_t* tmp = (uint8_t*)taosMemoryCalloc(*size, 1);
938
//   if(tmp == NULL) return -1;
939
//   int8_t   num = 0;
940
//   uint8_t *byte = tmp + *size - 1;
941
//
942
//   for (int i = n - 1; i >= 0; i--) {
943
//     *byte |= ((uint8_t)(z[i] - '0') << num);
944
//     if (num == 7) {
945
//       byte--;
946
//       num = 0;
947
//     } else {
948
//       num++;
949
//     }
950
//   }
951
//   *data = tmp;
952
//   return 0;
953
// }
954

955
static char valueOf(uint8_t symbol) {
181,562✔
956
  switch (symbol) {
181,562!
957
    case 0:
131,544✔
958
      return '0';
131,544✔
959
    case 1:
620✔
960
      return '1';
620✔
961
    case 2:
664✔
962
      return '2';
664✔
963
    case 3:
18,773✔
964
      return '3';
18,773✔
965
    case 4:
2,860✔
966
      return '4';
2,860✔
967
    case 5:
2,549✔
968
      return '5';
2,549✔
969
    case 6:
2,663✔
970
      return '6';
2,663✔
971
    case 7:
18,723✔
972
      return '7';
18,723✔
973
    case 8:
692✔
974
      return '8';
692✔
975
    case 9:
422✔
976
      return '9';
422✔
977
    case 10:
652✔
978
      return 'A';
652✔
979
    case 11:
216✔
980
      return 'B';
216✔
981
    case 12:
431✔
982
      return 'C';
431✔
983
    case 13:
85✔
984
      return 'D';
85✔
985
    case 14:
349✔
986
      return 'E';
349✔
987
    case 15:
319✔
988
      return 'F';
319✔
989
    default: {
×
990
      return -1;
×
991
    }
992
  }
993
}
994

995
int32_t taosAscii2Hex(const char *z, uint32_t n, void **data, uint32_t *size) {
2,454✔
996
  *size = n * 2 + HEX_PREFIX_LEN;
2,454✔
997
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size + 1, 1);
2,454!
998
  if (tmp == NULL) {
2,454!
999
    return terrno;
×
1000
  }
1001

1002
  *data = tmp;
2,454✔
1003
  *(tmp++) = '\\';
2,454✔
1004
  *(tmp++) = 'x';
2,454✔
1005
  for (int i = 0; i < n; i++) {
93,235✔
1006
    uint8_t val = z[i];
90,781✔
1007
    tmp[i * 2] = valueOf(val >> 4);
90,781✔
1008
    tmp[i * 2 + 1] = valueOf(val & 0x0F);
90,781✔
1009
  }
1010

1011
  return 0;
2,454✔
1012
}
1013

1014
int64_t tsnprintf(char *dst, int64_t size, const char *format, ...) {
26,268,580✔
1015
  if (dst == NULL || format == NULL) {
26,268,580!
1016
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
1017
    return 0;
×
1018
  }
1019
  if (size <= 0) return 0;
26,273,135!
1020
  if (size == 1) {
26,273,135!
UNCOV
1021
    dst[0] = '\0';
×
UNCOV
1022
    return 0;
×
1023
  }
1024
  if (size > SIZE_MAX) {
1025
    size = SIZE_MAX;
1026
  }
1027

1028
  int64_t ret;
1029
  va_list args;
1030
  va_start(args, format);
26,273,135✔
1031
  ret = vsnprintf(dst, size, format, args);
26,273,135✔
1032
  va_end(args);
26,273,135✔
1033
  if (ret >= size) {
26,273,135!
UNCOV
1034
    return size - 1;
×
1035
  } else {
1036
    return ret;
26,273,135✔
1037
  }
1038
}
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