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

taosdata / TDengine / #4910

30 Dec 2025 10:52AM UTC coverage: 65.864% (+0.3%) from 65.542%
#4910

push

travis-ci

web-flow
enh: drop multi-stream (#33962)

60 of 106 new or added lines in 4 files covered. (56.6%)

999 existing lines in 108 files now uncovered.

194877 of 295877 relevant lines covered (65.86%)

121300574.4 hits per line

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

59.44
/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) {
2,147,483,647✔
28
  if (str == NULL) {
2,147,483,647✔
29
    terrno = TSDB_CODE_INVALID_PARA;
×
30
    return NULL;
×
31
  }
32
#ifdef WINDOWS
33
  return _strdup(str);
34
#else
35
  char *p = strdup(str);
2,147,483,647✔
36
  if (NULL == p) {
2,147,483,647✔
37
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
38
  }
39
  return p;
2,147,483,647✔
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) {
1,108,439,525✔
148
  if (s == NULL) {
1,108,439,525✔
149
    return NULL;
×
150
  }
151
  char *p = strndup(s, size);
1,108,439,525✔
152
  if (NULL == p) {
1,108,439,525✔
153
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
154
  }
155
  return p;
1,108,428,981✔
156
}
157
#endif
158

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

169
#endif
170
}
171

172
int32_t taosStr2int64(const char *str, int64_t *val) {
2,147,483,647✔
173
  if (str == NULL || val == NULL) {
2,147,483,647✔
UNCOV
174
    return TSDB_CODE_INVALID_PARA;
×
175
  }
176
  SET_ERRNO(0);
2,147,483,647✔
177
  char   *endptr = NULL;
2,147,483,647✔
178
  int64_t ret = strtoll(str, &endptr, 10);
2,147,483,647✔
179
  if (ERRNO != 0) {
2,147,483,647✔
180
    return TAOS_SYSTEM_ERROR(ERRNO);
×
181
  } else {
182
    if (endptr == str) {
2,147,483,647✔
183
      return TSDB_CODE_INVALID_PARA;
1,639✔
184
    }
185
    *val = ret;
2,147,483,647✔
186
    return 0;
2,147,483,647✔
187
  }
188
}
189

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

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

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

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

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

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

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

298
int32_t taosUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes) {
2,147,483,647✔
299
  if ((f1_ucs4 == NULL || f2_ucs4 == NULL)) {
2,147,483,647✔
300
    return TSDB_CODE_INVALID_PARA;
×
301
  }
302
  for (int32_t i = 0; i < bytes; i += sizeof(TdUcs4)) {
2,147,483,647✔
303
    int32_t f1 = *(int32_t *)((char *)f1_ucs4 + i);
2,147,483,647✔
304
    int32_t f2 = *(int32_t *)((char *)f2_ucs4 + i);
2,147,483,647✔
305

306
    if ((f1 == 0 && f2 != 0) || (f1 != 0 && f2 == 0)) {
2,147,483,647✔
307
      return f1 - f2;
×
308
    } else if (f1 == 0 && f2 == 0) {
2,147,483,647✔
309
      return 0;
×
310
    }
311

312
    if (f1 != f2) {
2,147,483,647✔
313
      return f1 - f2;
2,147,483,647✔
314
    }
315
  }
316

317
  return 0;
2,147,483,647✔
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) {
2,147,483,647✔
357
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
358
  if(idx == NULL) {
2,147,483,647✔
359
    terrno = TSDB_CODE_INVALID_PARA;
×
360
    return (iconv_t)NULL;
×
361
  }
362

363
  int32_t retryLimit = 100, i = 0;
2,147,483,647✔
364

365
  if (charsetCxt == NULL){
2,147,483,647✔
366
    charsetCxt = tsCharsetCxt;
2,147,483,647✔
367
  }
368
  SConvInfo *info = (SConvInfo *)charsetCxt;
2,147,483,647✔
369
  if (info == NULL) {
2,147,483,647✔
370
    *idx = -1;
×
371
    if (type == M2C) {
×
372
      iconv_t c = iconv_open(DEFAULT_UNICODE_ENCODEC, "UTF-8");
×
373
      if ((iconv_t)-1 == c) {
×
374
        terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
375
      }
376
      return c;
×
377
    } else {
378
      iconv_t c = iconv_open("UTF-8", DEFAULT_UNICODE_ENCODEC);
×
379
      if ((iconv_t)-1 == c) {
×
380
        terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
381
      }
382
      return c;
×
383
    }
384
  }
385

386
  while (true) {
51,379✔
387
    if (i++ >= retryLimit) {
2,147,483,647✔
388
      uError("taosAcquireConv retry limit reached");
×
389
      return (iconv_t)-1;
×
390
    }
391

392
    int32_t used = atomic_add_fetch_32(&info->convUsed[type], 1);
2,147,483,647✔
393
    if (used > info->gConvMaxNum[type]) {
2,147,483,647✔
UNCOV
394
      (void)atomic_sub_fetch_32(&info->convUsed[type], 1);
×
395
      (void)sched_yield();
×
396
      continue;
51,379✔
397
    }
398

399
    break;
2,147,483,647✔
400
  }
401

402
  int32_t startId = ((uint32_t)(taosGetSelfPthreadId())) % info->gConvMaxNum[type];
2,147,483,647✔
403
  while (true) {
×
404
    if (info->gConv[type][startId].inUse) {
2,147,483,647✔
405
      startId = (startId + 1) % info->gConvMaxNum[type];
×
406
      continue;
×
407
    }
408

409
    int8_t old = atomic_val_compare_exchange_8(&info->gConv[type][startId].inUse, 0, 1);
2,147,483,647✔
410
    if (0 == old) {
2,147,483,647✔
411
      break;
2,147,483,647✔
412
    }
413
  }
414

415
  *idx = startId;
2,147,483,647✔
416
  if ((iconv_t)0 == info->gConv[type][startId].conv) {
2,147,483,647✔
417
    return (iconv_t)-1;
×
418
  } else {
419
    return info->gConv[type][startId].conv;
2,147,483,647✔
420
  }
421
#else
422
  terrno = TSDB_CODE_APP_ERROR;
423
  return (iconv_t)-1;
424
#endif
425
}
426

427
void taosReleaseConv(int32_t idx, iconv_t conv, ConvType type, void *charsetCxt) {
2,147,483,647✔
428
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
429
  if (idx < 0) {
2,147,483,647✔
430
    (void)iconv_close(conv);
×
431
    return;
×
432
  }
433

434
  if (charsetCxt == NULL) {
2,147,483,647✔
435
    charsetCxt = tsCharsetCxt;
2,147,483,647✔
436
  }
437
  SConvInfo *info = (SConvInfo *)charsetCxt;
2,147,483,647✔
438

439
  atomic_store_8(&info->gConv[type][idx].inUse, 0);
2,147,483,647✔
440
  (void)atomic_sub_fetch_32(&info->convUsed[type], 1);
2,147,483,647✔
441
#endif
442
}
443

444
bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len, void* charsetCxt) {
2,147,483,647✔
445
  if (ucs4_max_len == 0) {
2,147,483,647✔
446
    return true;
109,495,655✔
447
  }
448
  if (ucs4_max_len < 0 || mbs == NULL || ucs4 == NULL) {
2,147,483,647✔
449
    terrno = TSDB_CODE_INVALID_PARA;
13✔
450
    return false;
×
451
  }
452
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
453
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
454
  terrno = TSDB_CODE_APP_ERROR;
455
  return false;
456
#else
457
  (void)memset(ucs4, 0, ucs4_max_len);
2,147,483,647✔
458

459
  int32_t idx = -1;
2,147,483,647✔
460
  iconv_t conv = taosAcquireConv(&idx, M2C, charsetCxt);
2,147,483,647✔
461
  if ((iconv_t)-1 == conv) {
2,147,483,647✔
462
    return false;
×
463
  }
464

465
  size_t ucs4_input_len = mbsLength;
2,147,483,647✔
466
  size_t outLeft = ucs4_max_len;
2,147,483,647✔
467
  if (iconv(conv, (char **)&mbs, &ucs4_input_len, (char **)&ucs4, &outLeft) == -1) {
2,147,483,647✔
468
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
118,240✔
469
    taosReleaseConv(idx, conv, M2C, charsetCxt);
118,240✔
470
    return false;
118,253✔
471
  }
472

473
  taosReleaseConv(idx, conv, M2C, charsetCxt);
2,147,483,647✔
474
  if (len != NULL) {
2,147,483,647✔
475
    *len = (int32_t)(ucs4_max_len - outLeft);
2,147,483,647✔
476
    if (*len < 0) {
2,147,483,647✔
477
      // can not happen
478
      terrno = TSDB_CODE_APP_ERROR;
×
479
      return false;
×
480
    }
481
  }
482

483
  return true;
2,147,483,647✔
484
#endif
485
}
486

487
// if success, return the number of bytes written to mbs ( >= 0)
488
// otherwise return error code ( < 0)
489
int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs, void* charsetCxt) {
712,399,530✔
490
  if (ucs4_max_len == 0) {
712,399,530✔
491
    return 0;
18,684✔
492
  }
493
  if (ucs4_max_len < 0 || ucs4 == NULL || mbs == NULL) {
712,380,846✔
UNCOV
494
    terrno = TSDB_CODE_INVALID_PARA;
×
495
    return terrno;
×
496
  }
497
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
498
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
499
  terrno = TSDB_CODE_APP_ERROR;
500
  return terrno;
501
#else
502

503
  int32_t idx = -1;
712,388,934✔
504
  int32_t code = 0;
712,396,462✔
505
  iconv_t conv = taosAcquireConv(&idx, C2M, charsetCxt);
712,396,462✔
506
  if ((iconv_t)-1 == conv) {
712,416,322✔
507
    return terrno;
×
508
  }
509

510
  size_t ucs4_input_len = ucs4_max_len;
712,416,322✔
511
  size_t outLen = ucs4_max_len;
712,405,104✔
512
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
712,415,805✔
513
    code = TAOS_SYSTEM_ERROR(ERRNO);
×
514
    taosReleaseConv(idx, conv, C2M, charsetCxt);
×
515
    terrno = code;
×
516
    return code;
×
517
  }
518

519
  taosReleaseConv(idx, conv, C2M, charsetCxt);
712,346,391✔
520

521
  return (int32_t)(ucs4_max_len - outLen);
712,393,830✔
522
#endif
523
}
524

525
// if success, return the number of bytes written to mbs ( >= 0)
526
// otherwise return error code ( < 0)
527
int32_t taosUcs4ToMbsEx(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs, iconv_t conv) {
2,147,483,647✔
528
  if (ucs4_max_len == 0) {
2,147,483,647✔
529
    return 0;
53,976,322✔
530
  }
531
  if (ucs4_max_len < 0 || ucs4 == NULL || mbs == NULL) {
2,147,483,647✔
532
    terrno = TSDB_CODE_INVALID_PARA;
300✔
533
    return terrno;
×
534
  }
535
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
536
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
537
  terrno = TSDB_CODE_APP_ERROR;
538
  return terrno;
539
#else
540

541
  size_t ucs4_input_len = ucs4_max_len;
2,147,483,647✔
542
  size_t outLen = ucs4_max_len;
2,147,483,647✔
543
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
2,147,483,647✔
544
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
61✔
545
    return terrno;
61✔
546
  }
547

548
  return (int32_t)(ucs4_max_len - outLen);
2,147,483,647✔
549
#endif
550
}
551

552
bool taosValidateEncodec(const char *encodec) {
1,930,329✔
553
  if (encodec == NULL) {
1,930,329✔
554
    terrno = TSDB_CODE_INVALID_PARA;
×
555
    return false;
×
556
  }
557
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
558
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
559
  terrno = TSDB_CODE_APP_ERROR;
560
  return false;
561
#else
562
  iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC);
1,930,329✔
563
  if (cd == (iconv_t)(-1)) {
1,930,329✔
564
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
565
    return false;
×
566
  }
567

568
  (void)iconv_close(cd);
1,930,329✔
569
  return true;
1,930,329✔
570
#endif
571
}
572

573
int32_t taosUcs4len(TdUcs4 *ucs4) {
×
574
  TdUcs4 *wstr = (TdUcs4 *)ucs4;
×
575
  if (NULL == wstr) {
×
576
    return 0;
×
577
  }
578

579
  int32_t n = 0;
×
580
  while (1) {
581
    if (0 == *wstr++) {
×
582
      break;
×
583
    }
584
    n++;
×
585
  }
586

587
  return n;
×
588
}
589

590
// dst buffer size should be at least 2*len + 1
591
int32_t taosHexEncode(const unsigned char *src, char *dst, int32_t len, int32_t bufSize) {
62,969✔
592
  if (!dst || !src || bufSize <= 0) {
62,969✔
593
    terrno = TSDB_CODE_INVALID_PARA;
×
594
    return terrno;
×
595
  }
596

597
  for (int32_t i = 0; i < len; ++i) {
1,010,061✔
598
    (void)snprintf(dst + i * 2, bufSize - i * 2, "%02x", src[i]);
947,092✔
599
  }
600

601
  return 0;
62,969✔
602
}
603

604
int32_t taosHexDecode(const char *src, char *dst, int32_t len) {
×
605
  if (!src || !dst || len <= 0) {
×
606
    terrno = TSDB_CODE_INVALID_PARA;
×
607
    return terrno;
×
608
  }
609

610
  uint8_t hn, ln, out;
×
611
  for (int i = 0, j = 0; i < len * 2; i += 2, ++j) {
×
612
    hn = src[i] > '9' ? src[i] - 'a' + 10 : src[i] - '0';
×
613
    ln = src[i + 1] > '9' ? src[i + 1] - 'a' + 10 : src[i + 1] - '0';
×
614

615
    out = (hn << 4) | ln;
×
616
    (void)memcpy(dst + j, &out, 1);
×
617
  }
618

619
  return 0;
×
620
}
621

622
#ifdef TD_ASTRA
623
#include <wchar.h>
624
#include <stdbool.h>
625
#include <stdint.h>
626

627
typedef struct {
628
    uint32_t start;
629
    uint32_t end;
630
} SUnicodeRange;
631

632
static const SUnicodeRange __eaw_ranges[] = {
633
    {0x1100, 0x115F},   {0x2329, 0x232A}, {0x2E80, 0x303E}, {0x3040, 0xA4CF},
634
    {0xAC00, 0xD7AF},   {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0x20000, 0x2FFFD},
635
    {0x30000, 0x3FFFD}, {0xFF00, 0xFFEF}, {0xA000, 0xA48F}, {0x13A0, 0x13FF}
636
};
637

638
static const int __n_eaw_ranges = sizeof(__eaw_ranges) / sizeof(__eaw_ranges[0]);
639

640
static bool isEawWideChar(wchar_t code_point) {
641
    int low = 0;
642
    int high = __n_eaw_ranges - 1;
643

644
    while (low <= high) {
645
        int mid = (low + high) / 2;
646
        if (code_point < __eaw_ranges[mid].start) {
647
            high = mid - 1;
648
        } else if (code_point > __eaw_ranges[mid].end) {
649
            low = mid + 1;
650
        } else {
651
            return true;
652
        }
653
    }
654
    return false;
655
}
656

657
int wcwidth(wchar_t c) {
658
    if (c < 0x20 || (c >= 0x7F && c <= 0x9F)) {
659
        return 0;
660
    }
661
    if (isEawWideChar(c)) {
662
        return 2;
663
    }
664
    if (c >= 0x0300 && c <= 0x036F) {
665
        return 0;
666
    }
667
    return 1;
668
}
669

670
#endif
671

672
int32_t taosWcharWidth(TdWchar wchar) { return wcwidth(wchar); }
421,508,515✔
673

674
int32_t taosWcharsWidth(TdWchar *pWchar, int32_t size) {
×
675
  if (pWchar == NULL || size <= 0) {
×
676
    terrno = TSDB_CODE_INVALID_PARA;
×
677
    return terrno;
×
678
  }
679
#ifndef TD_ASTRA
680
  return wcswidth(pWchar, size);
×
681
#else
682
  int32_t width = 0;
683
  for (int32_t i = 0; i < size; ++i) {
684
    width += wcwidth(pWchar[i]);
685
  }
686
  return width;
687
#endif
688
}
689

690
int32_t taosMbToWchar(TdWchar *pWchar, const char *pStr, int32_t size) {
421,508,172✔
691
  if (pWchar == NULL || pStr == NULL || size <= 0) {
421,508,172✔
692
    terrno = TSDB_CODE_INVALID_PARA;
×
693
    return terrno;
×
694
  }
695
#ifndef TD_ASTRA
696
  return mbtowc(pWchar, pStr, size);
421,508,172✔
697
#else
698
  return mbrtowc(pWchar, &pStr, size, NULL);
699
#endif
700
}
701

702
#ifdef TD_ASTRA
703
size_t mbstowcs(wchar_t *dest, const char *src, size_t n) {
704
  if (src == NULL) {
705
    return 0;
706
  }
707

708
  size_t count = 0;
709
  int    result;
710
  while (*src && count < n) {
711
    result = mbrtowc(dest, src, MB_CUR_MAX, NULL);
712
    if (result == -1 || result == 0) {
713
      return -1;
714
    }
715
    src += result;
716
    dest++;
717
    count++;
718
  }
719

720
  if (count < n) {
721
    *dest = L'\0';
722
  }
723
  return count;
724
}
725
#endif
726

727
int32_t taosMbsToWchars(TdWchar *pWchars, const char *pStrs, int32_t size) {
×
728
  if (pWchars == NULL || pStrs == NULL || size <= 0) {
×
729
    terrno = TSDB_CODE_INVALID_PARA;
×
730
    return terrno;
×
731
  }
732
  return mbstowcs(pWchars, pStrs, size);
×
733
}
734

735
int32_t taosWcharToMb(char *pStr, TdWchar wchar) {
×
736
  OS_PARAM_CHECK(pStr);
×
737
#ifndef TD_ASTRA
738
  return wctomb(pStr, wchar);
×
739
#else
740
  return wcrtomb(pStr, wchar, NULL);
741
#endif
742
}
743

744
char *taosStrCaseStr(const char *str, const char *pattern) {
×
745
  if (str == NULL) {
×
746
    terrno = TSDB_CODE_INVALID_PARA;
×
747
    return NULL;
×
748
  }
749
  if (!pattern || !*pattern) return (char *)str;
×
750

751
  size_t i;
752
  for (; *str; str++) {
×
753
    if (toupper(*str) == toupper(*pattern)) {
×
754
      for (i = 1;; i++) {
×
755
        if (!pattern[i]) return (char *)str;
×
756
        if (toupper(str[i]) != toupper(pattern[i])) break;
×
757
      }
758
    }
759
  }
760
  return NULL;
×
761
}
762

763
int64_t taosStr2Int64(const char *str, char **pEnd, int32_t radix) {
2,147,483,647✔
764
  if (str == NULL) {
2,147,483,647✔
765
    terrno = TSDB_CODE_INVALID_PARA;
×
766
    return 0;
×
767
  }
768
  int64_t tmp = strtoll(str, pEnd, radix);
2,147,483,647✔
769
#if defined(DARWIN) || defined(_ALPINE)
770
  if (ERRNO == EINVAL) SET_ERRNO(0);
771
#endif
772
  return tmp;
2,147,483,647✔
773
}
774

775
uint64_t taosStr2UInt64(const char *str, char **pEnd, int32_t radix) {
2,147,483,647✔
776
  if (str == NULL) {
2,147,483,647✔
777
    terrno = TSDB_CODE_INVALID_PARA;
×
778
    return 0;
×
779
  }
780
  uint64_t tmp = strtoull(str, pEnd, radix);
2,147,483,647✔
781
#if defined(DARWIN) || defined(_ALPINE)
782
  if (ERRNO == EINVAL) SET_ERRNO(0);
783
#endif
784
  return tmp;
2,147,483,647✔
785
}
786

787
int32_t taosStr2Int32(const char *str, char **pEnd, int32_t radix) {
2,147,483,647✔
788
  if (str == NULL) {
2,147,483,647✔
789
    terrno = TSDB_CODE_INVALID_PARA;
×
790
    return 0;
×
791
  }
792
  int32_t tmp = strtol(str, pEnd, radix);
2,147,483,647✔
793
#if defined(DARWIN) || defined(_ALPINE)
794
  if (ERRNO == EINVAL) SET_ERRNO(0);
795
#endif
796
  return tmp;
2,147,483,647✔
797
}
798

799
uint32_t taosStr2UInt32(const char *str, char **pEnd, int32_t radix) {
239,839✔
800
  if (str == NULL) {
239,839✔
801
    terrno = TSDB_CODE_INVALID_PARA;
×
802
    return 0;
×
803
  }
804
  uint32_t tmp = strtol(str, pEnd, radix);
239,839✔
805
#if defined(DARWIN) || defined(_ALPINE)
806
  if (ERRNO == EINVAL) SET_ERRNO(0);
807
#endif
808
  return tmp;
239,839✔
809
}
810

811
int16_t taosStr2Int16(const char *str, char **pEnd, int32_t radix) {
2,261,431✔
812
  if (str == NULL) {
2,261,431✔
813
    terrno = TSDB_CODE_INVALID_PARA;
×
814
    return 0;
×
815
  }
816
  int32_t tmp = strtol(str, pEnd, radix);
2,261,431✔
817
#if defined(DARWIN) || defined(_ALPINE)
818
  if (ERRNO == EINVAL) SET_ERRNO(0);
819
#endif
820
  return (int16_t)tmp;
2,261,431✔
821
}
822

823
uint16_t taosStr2UInt16(const char *str, char **pEnd, int32_t radix) {
9,484,350✔
824
  if (str == NULL) {
9,484,350✔
825
    terrno = TSDB_CODE_INVALID_PARA;
×
826
    return 0;
×
827
  }
828
  uint32_t tmp = strtoul(str, pEnd, radix);
9,484,350✔
829
#if defined(DARWIN) || defined(_ALPINE)
830
  if (ERRNO == EINVAL) SET_ERRNO(0);
831
#endif
832
  return (uint16_t)tmp;
9,484,543✔
833
}
834

835
int8_t taosStr2Int8(const char *str, char **pEnd, int32_t radix) {
1,299,645✔
836
  if (str == NULL) {
1,299,645✔
837
    terrno = TSDB_CODE_INVALID_PARA;
×
838
    return 0;
×
839
  }
840
  int32_t tmp = strtol(str, pEnd, radix);
1,299,645✔
841
  return tmp;
1,299,645✔
842
}
843

844
uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix) {
273,164✔
845
  if (str == NULL) {
273,164✔
846
    terrno = TSDB_CODE_INVALID_PARA;
×
847
    return 0;
×
848
  }
849
  uint32_t tmp = strtoul(str, pEnd, radix);
273,164✔
850
#if defined(DARWIN) || defined(_ALPINE)
851
  if (ERRNO == EINVAL) SET_ERRNO(0);
852
#endif
853
  return tmp;
273,164✔
854
}
855

856
double taosStr2Double(const char *str, char **pEnd) {
2,147,483,647✔
857
  if (str == NULL) {
2,147,483,647✔
858
    terrno = TSDB_CODE_INVALID_PARA;
×
859
    return 0;
×
860
  }
861
  double tmp = strtod(str, pEnd);
2,147,483,647✔
862
  return tmp;
2,147,483,647✔
863
}
864

865
float taosStr2Float(const char *str, char **pEnd) {
5,172,296✔
866
  if (str == NULL) {
5,172,296✔
867
    terrno = TSDB_CODE_INVALID_PARA;
×
868
    return 0;
×
869
  }
870
  float tmp = strtof(str, pEnd);
5,172,296✔
871
  return tmp;
5,172,296✔
872
}
873

874
#define HEX_PREFIX_LEN 2  // \x
875
bool isHex(const char *z, uint32_t n) {
2,147,483,647✔
876
  if (n < HEX_PREFIX_LEN) return false;
2,147,483,647✔
877
  if (z[0] == '\\' && z[1] == 'x') return true;
2,147,483,647✔
878
  return false;
2,147,483,647✔
879
}
880

881
bool isValidateHex(const char *z, uint32_t n) {
3,356,808✔
882
  if (!z) {
3,356,808✔
883
    terrno = TSDB_CODE_INVALID_PARA;
×
884
    return false;
×
885
  }
886
  if ((n & 1) != 0) return false;
3,356,808✔
887
  for (size_t i = HEX_PREFIX_LEN; i < n; i++) {
2,147,483,647✔
888
    if (isxdigit(z[i]) == 0) {
2,147,483,647✔
889
      return false;
×
890
    }
891
  }
892
  return true;
3,356,808✔
893
}
894

895
int32_t taosHex2Ascii(const char *z, uint32_t n, void **data, uint32_t *size) {
3,356,808✔
896
  OS_PARAM_CHECK(z);
3,356,808✔
897
  OS_PARAM_CHECK(data);
3,356,808✔
898
  OS_PARAM_CHECK(size);
3,356,808✔
899
  n -= HEX_PREFIX_LEN;  // remove 0x
3,356,808✔
900
  z += HEX_PREFIX_LEN;
3,356,808✔
901
  *size = n / HEX_PREFIX_LEN;
3,356,808✔
902
  if (*size == 0) {
3,356,808✔
903
    if (!(*data = taosStrdup(""))) {
8,737✔
904
      return terrno;
×
905
    }
906
    return 0;
8,737✔
907
  }
908

909
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size, 1);
3,348,071✔
910
  if (tmp == NULL) {
3,348,071✔
911
    return terrno;
×
912
  }
913

914
  int8_t   num = 0;
3,348,071✔
915
  uint8_t *byte = tmp + *size - 1;
3,348,071✔
916

917
  for (int i = n - 1; i >= 0; i--) {
2,147,483,647✔
918
    if (z[i] >= 'a') {
2,147,483,647✔
919
      *byte |= ((uint8_t)(10 + (z[i] - 'a')) << (num * 4));
2,147,483,647✔
920
    } else if (z[i] >= 'A') {
2,147,483,647✔
921
      *byte |= ((uint8_t)(10 + (z[i] - 'A')) << (num * 4));
13,465✔
922
    } else {
923
      *byte |= ((uint8_t)(z[i] - '0') << (num * 4));
2,147,483,647✔
924
    }
925
    if (num == 1) {
2,147,483,647✔
926
      byte--;
2,147,483,647✔
927
      num = 0;
2,147,483,647✔
928
    } else {
929
      num++;
2,147,483,647✔
930
    }
931
  }
932
  *data = tmp;
3,348,071✔
933

934
  return 0;
3,348,071✔
935
}
936

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

963
static char valueOf(uint8_t symbol) {
28,275,882✔
964
  switch (symbol) {
28,275,882✔
965
    case 0:
136,820✔
966
      return '0';
136,820✔
967
    case 1:
226,643✔
968
      return '1';
226,643✔
969
    case 2:
11,741,843✔
970
      return '2';
11,741,843✔
971
    case 3:
1,781,434✔
972
      return '3';
1,781,434✔
973
    case 4:
581,166✔
974
      return '4';
581,166✔
975
    case 5:
717,196✔
976
      return '5';
717,196✔
977
    case 6:
11,611,968✔
978
      return '6';
11,611,968✔
979
    case 7:
84,818✔
980
      return '7';
84,818✔
981
    case 8:
289,357✔
982
      return '8';
289,357✔
983
    case 9:
276,993✔
984
      return '9';
276,993✔
985
    case 10:
45,628✔
986
      return 'A';
45,628✔
987
    case 11:
113,243✔
988
      return 'B';
113,243✔
989
    case 12:
317,136✔
990
      return 'C';
317,136✔
991
    case 13:
99,607✔
992
      return 'D';
99,607✔
993
    case 14:
244,934✔
994
      return 'E';
244,934✔
995
    case 15:
7,446✔
996
      return 'F';
7,446✔
997
    default: {
×
998
      return -1;
×
999
    }
1000
  }
1001
}
1002

1003
int32_t taosAscii2Hex(const char *z, uint32_t n, void **data, uint32_t *size) {
449,013✔
1004
  *size = n * 2 + HEX_PREFIX_LEN;
449,013✔
1005
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size + 1, 1);
449,013✔
1006
  if (tmp == NULL) {
449,073✔
1007
    return terrno;
×
1008
  }
1009

1010
  *data = tmp;
449,073✔
1011
  *(tmp++) = '\\';
449,073✔
1012
  *(tmp++) = 'x';
449,073✔
1013
  for (int i = 0; i < n; i++) {
14,586,974✔
1014
    uint8_t val = z[i];
14,137,951✔
1015
    tmp[i * 2] = valueOf(val >> 4);
14,137,951✔
1016
    tmp[i * 2 + 1] = valueOf(val & 0x0F);
14,137,951✔
1017
  }
1018

1019
  return 0;
449,023✔
1020
}
1021

1022
int64_t tsnprintf(char *dst, int64_t size, const char *format, ...) {
2,147,483,647✔
1023
  if (dst == NULL || format == NULL) {
2,147,483,647✔
1024
    terrno = TSDB_CODE_INVALID_PARA;
1✔
1025
    return 0;
×
1026
  }
1027
  if (size <= 0) return 0;
2,147,483,647✔
1028
  if (size == 1) {
2,147,483,647✔
1029
    dst[0] = '\0';
×
1030
    return 0;
×
1031
  }
1032
  if (size > SIZE_MAX) {
1033
    size = SIZE_MAX;
1034
  }
1035

1036
  int64_t ret;
1037
  va_list args;
2,147,483,647✔
1038
  va_start(args, format);
2,147,483,647✔
1039
  ret = vsnprintf(dst, size, format, args);
2,147,483,647✔
1040
  va_end(args);
2,147,483,647✔
1041
  if (ret >= size) {
2,147,483,647✔
1042
    return size - 1;
172,200✔
1043
  } else {
1044
    return ret;
2,147,483,647✔
1045
  }
1046
}
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