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

taosdata / TDengine / #3525

10 Nov 2024 03:50AM UTC coverage: 60.818% (-0.08%) from 60.898%
#3525

push

travis-ci

web-flow
Merge pull request #28709 from taosdata/main

merge: from main to 3.0 branch

118634 of 249004 branches covered (47.64%)

Branch coverage included in aggregate %.

136 of 169 new or added lines in 23 files covered. (80.47%)

542 existing lines in 129 files now uncovered.

199071 of 273386 relevant lines covered (72.82%)

15691647.46 hits per line

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

64.07
/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) {
203,448,544✔
28
#ifdef WINDOWS
29
  return _strdup(str);
30
#else
31
  char* p = strdup(str);
203,448,544✔
32
  if (str != NULL && NULL == p) {
203,448,544!
33
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
34
  }
35
  return p;
203,448,544✔
36
  
37
#endif
38
}
39

40
#ifdef WINDOWS
41

42
// No errors are expected to occur
43
char *strsep(char **stringp, const char *delim) {
44
  char       *s;
45
  const char *spanp;
46
  int32_t     c, sc;
47
  char       *tok;
48
  if ((s = *stringp) == NULL) return (NULL);
49
  for (tok = s;;) {
50
    c = *s++;
51
    spanp = delim;
52
    do {
53
      if ((sc = *spanp++) == c) {
54
        if (c == 0)
55
          s = NULL;
56
        else
57
          s[-1] = 0;
58
        *stringp = s;
59
        return (tok);
60
      }
61
    } while (sc != 0);
62
  }
63
  /* NOTREACHED */
64
}
65
/* Duplicate a string, up to at most size characters */
66
char *taosStrndup(const char *s, int size) {
67
  if (s == NULL) return NULL;
68
  size_t l;
69
  char  *s2;
70
  l = strlen(s);
71
  if (l > size) l = size;
72
  s2 = malloc(l + 1);
73
  if (s2) {
74
    tstrncpy(s2, s, l + 1);
75
    s2[l] = '\0';
76
  } else {
77
    terrno = TSDB_CODE_OUT_OF_MEMORY;
78
  }
79
  return s2;
80
}
81
/* Copy no more than N characters of SRC to DEST, returning the address of
82
   the terminating '\0' in DEST, if any, or else DEST + N.  */
83
char *stpncpy(char *dest, const char *src, int n) {
84
  size_t size = strnlen(src, n);
85
  memcpy(dest, src, size);
86
  dest += size;
87
  if (size == n) return dest;
88
  return memset(dest, '\0', n - size);
89
}
90
#else
91
char *taosStrndup(const char *s, int size) {
340,265,583✔
92
  if (s == NULL) {
340,265,583!
93
    return NULL;
×
94
  }
95
  char *p = strndup(s, size);
340,265,583✔
96
  if (NULL == p) {
340,265,583!
97
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
98
  }
99
  return p;
340,265,583✔
100
}
101
#endif
102

103
int32_t taosStr2int64(const char *str, int64_t *val) {
339✔
104
  if (str == NULL || val == NULL) {
339!
105
    return TSDB_CODE_INVALID_PARA;
×
106
  }
107
  char   *endptr = NULL;
339✔
108
  int64_t ret = strtoll(str, &endptr, 10);
339✔
109
  if (errno == ERANGE && (ret == LLONG_MAX || ret == LLONG_MIN)) {
338!
110
    return TAOS_SYSTEM_ERROR(errno);
×
111
  } else if (errno == EINVAL && ret == 0) {
338!
112
    return TSDB_CODE_INVALID_PARA;
×
113
  } else {
114
    *val = ret;
338✔
115
    return 0;
338✔
116
  }
117
}
118

119
int32_t taosStr2int16(const char *str, int16_t *val) {
×
120
  int64_t tmp = 0;
×
121
  int32_t code = taosStr2int64(str, &tmp);
×
122
  if (code) {
×
123
    return code;
×
124
  } else if (tmp > INT16_MAX || tmp < INT16_MIN) {
×
125
    return TAOS_SYSTEM_ERROR(ERANGE);
×
126
  } else {
127
    *val = (int16_t)tmp;
×
128
    return 0;
×
129
  }
130
}
131

132
int32_t taosStr2int32(const char *str, int32_t *val) {
42✔
133
  int64_t tmp = 0;
42✔
134
  int32_t code = taosStr2int64(str, &tmp);
42✔
135
  if (code) {
42!
136
    return code;
×
137
  } else if (tmp > INT32_MAX || tmp < INT32_MIN) {
42!
138
    return TAOS_SYSTEM_ERROR(ERANGE);
×
139
  } else {
140
    *val = (int32_t)tmp;
42✔
141
    return 0;
42✔
142
  }
143
}
144

145
int32_t taosStr2int8(const char *str, int8_t *val) {
×
146
  int64_t tmp = 0;
×
147
  int32_t code = taosStr2int64(str, &tmp);
×
148
  if (code) {
×
149
    return code;
×
150
  } else if (tmp > INT8_MAX || tmp < INT8_MIN) {
×
151
    return TAOS_SYSTEM_ERROR(ERANGE);
×
152
  } else {
153
    *val = (int8_t)tmp;
×
154
    return 0;
×
155
  }
156
}
157

158
int32_t tasoUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes) {
169,298,822✔
159
  for (int32_t i = 0; i < bytes; i += sizeof(TdUcs4)) {
1,015,402,373✔
160
    int32_t f1 = *(int32_t *)((char *)f1_ucs4 + i);
954,148,045✔
161
    int32_t f2 = *(int32_t *)((char *)f2_ucs4 + i);
954,148,045✔
162

163
    if ((f1 == 0 && f2 != 0) || (f1 != 0 && f2 == 0)) {
954,148,045!
164
      return f1 - f2;
×
165
    } else if (f1 == 0 && f2 == 0) {
954,148,045!
166
      return 0;
×
167
    }
168

169
    if (f1 != f2) {
954,148,045✔
170
      return f1 - f2;
108,044,494✔
171
    }
172
  }
173

174
  return 0;
61,254,328✔
175

176
  //#if 0
177
  //  int32_t ucs4_max_len = bytes + 4;
178
  //  char *f1_mbs = taosMemoryCalloc(bytes, 1);
179
  //  char *f2_mbs = taosMemoryCalloc(bytes, 1);
180
  //  if (taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs) < 0) {
181
  //    return -1;
182
  //  }
183
  //  if (taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs) < 0) {
184
  //    return -1;
185
  //  }
186
  //  int32_t ret = strcmp(f1_mbs, f2_mbs);
187
  //  taosMemoryFree(f1_mbs);
188
  //  taosMemoryFree(f2_mbs);
189
  //  return ret;
190
  //#endif
191
}
192

193
int32_t tasoUcs4Copy(TdUcs4 *target_ucs4, TdUcs4 *source_ucs4, int32_t len_ucs4) {
×
194
  if (taosMemorySize(target_ucs4) < len_ucs4 * sizeof(TdUcs4)) {
×
195
    terrno = TSDB_CODE_INVALID_PARA;
×
196
    return terrno;
×
197
  }
198
  
199
  (void)memcpy(target_ucs4, source_ucs4, len_ucs4 * sizeof(TdUcs4));
×
200

201
  return TSDB_CODE_SUCCESS;
×
202
}
203

204
typedef struct {
205
  iconv_t conv;
206
  int8_t  inUse;
207
} SConv;
208

209
// 0: Mbs --> Ucs4
210
// 1: Ucs4--> Mbs
211
SConv  *gConv[2] = {NULL, NULL};
212
int32_t convUsed[2] = {0, 0};
213
int32_t gConvMaxNum[2] = {0, 0};
214

215
int32_t taosConvInit(void) {
6,482✔
216
  int8_t M2C = 0;
6,482✔
217
  gConvMaxNum[M2C] = 512;
6,482✔
218
  gConvMaxNum[1 - M2C] = 512;
6,482✔
219

220
  gConv[M2C] = taosMemoryCalloc(gConvMaxNum[M2C], sizeof(SConv));
6,482✔
221
  if (gConv[M2C] == NULL) {
6,482!
222
    return terrno;
×
223
  }
224

225
  gConv[1 - M2C] = taosMemoryCalloc(gConvMaxNum[1 - M2C], sizeof(SConv));
6,482✔
226
  if (gConv[1 - M2C] == NULL) {
6,482!
227
    taosMemoryFree(gConv[M2C]);
×
228
    return terrno;
×
229
  }
230

231
  for (int32_t i = 0; i < gConvMaxNum[M2C]; ++i) {
3,325,266✔
232
    gConv[M2C][i].conv = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset);
3,318,784✔
233
    if ((iconv_t)-1 == gConv[M2C][i].conv) {
3,318,784!
234
      terrno = TAOS_SYSTEM_ERROR(errno);
×
235
      return terrno;
×
236
    }
237
  }
238
  for (int32_t i = 0; i < gConvMaxNum[1 - M2C]; ++i) {
3,325,266✔
239
    gConv[1 - M2C][i].conv = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC);
3,318,784✔
240
    if ((iconv_t)-1 == gConv[1 - M2C][i].conv) {
3,318,784!
241
      terrno = TAOS_SYSTEM_ERROR(errno);
×
242
      return terrno;
×
243
    }
244
  }
245

246
  return 0;
6,482✔
247
}
248

249
void taosConvDestroy() {
6,481✔
250
  int8_t M2C = 0;
6,481✔
251
  for (int32_t i = 0; i < gConvMaxNum[M2C]; ++i) {
3,324,753✔
252
    (void)iconv_close(gConv[M2C][i].conv);
3,318,272✔
253
  }
254
  for (int32_t i = 0; i < gConvMaxNum[1 - M2C]; ++i) {
3,324,753✔
255
    (void)iconv_close(gConv[1 - M2C][i].conv);
3,318,272✔
256
  }
257
  taosMemoryFreeClear(gConv[M2C]);
6,481!
258
  taosMemoryFreeClear(gConv[1 - M2C]);
6,481!
259
  gConvMaxNum[M2C] = -1;
6,481✔
260
  gConvMaxNum[1 - M2C] = -1;
6,481✔
261
}
6,481✔
262

263
iconv_t taosAcquireConv(int32_t *idx, ConvType type) {
394,397,145✔
264
  if (gConvMaxNum[type] <= 0) {
394,397,145!
265
    *idx = -1;
×
266
    if (type == M2C) {
×
267
      iconv_t c = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset);
×
268
      if ((iconv_t)-1 == c) {
×
269
        terrno = TAOS_SYSTEM_ERROR(errno);
×
270
      }
271
      return c;
×
272
    } else {
273
      iconv_t c = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC);
×
274
      if ((iconv_t)-1 == c) {
×
275
        terrno = TAOS_SYSTEM_ERROR(errno);
×
276
      }
277
      return c;
×
278
    }
279
  }
280

281
  while (true) {
×
282
    int32_t used = atomic_add_fetch_32(&convUsed[type], 1);
394,397,145✔
283
    if (used > gConvMaxNum[type]) {
394,923,105!
284
      used = atomic_sub_fetch_32(&convUsed[type], 1);
×
285
      (void)sched_yield();
×
286
      continue;
×
287
    }
288

289
    break;
395,111,179✔
290
  }
291

292
  int32_t startId = taosGetSelfPthreadId() % gConvMaxNum[type];
395,111,179✔
293
  while (true) {
11,548✔
294
    if (gConv[type][startId].inUse) {
394,974,498✔
295
      startId = (startId + 1) % gConvMaxNum[type];
337✔
296
      continue;
337✔
297
    }
298

299
    int8_t old = atomic_val_compare_exchange_8(&gConv[type][startId].inUse, 0, 1);
394,974,161✔
300
    if (0 == old) {
395,135,265✔
301
      break;
395,124,054✔
302
    }
303
  }
304

305
  *idx = startId;
395,124,054✔
306
  if ((iconv_t)0 == gConv[type][startId].conv) {
395,124,054!
307
    return (iconv_t)-1;
×
308
  } else {
309
    return gConv[type][startId].conv;
395,124,054✔
310
  }
311
}
312

313
void taosReleaseConv(int32_t idx, iconv_t conv, ConvType type) {
394,648,642✔
314
  if (idx < 0) {
394,648,642!
315
    (void)iconv_close(conv);
×
316
    return;
×
317
  }
318

319
  atomic_store_8(&gConv[type][idx].inUse, 0);
394,648,642✔
320
  (void)atomic_sub_fetch_32(&convUsed[type], 1);
395,172,588✔
321
}
322

323
bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len) {
78,895,978✔
324
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
325
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
326
  terrno = TSDB_CODE_APP_ERROR;
327
  return false;
328
#else
329
  (void)memset(ucs4, 0, ucs4_max_len);
78,895,978✔
330

331
  int32_t idx = -1;
78,895,978✔
332
  iconv_t conv = taosAcquireConv(&idx, M2C);
78,895,978✔
333
  if ((iconv_t)-1 == conv) {
79,125,725!
334
    return false;
×
335
  }
336
  
337
  size_t  ucs4_input_len = mbsLength;
79,125,725✔
338
  size_t  outLeft = ucs4_max_len;
79,125,725✔
339
  if (iconv(conv, (char **)&mbs, &ucs4_input_len, (char **)&ucs4, &outLeft) == -1) {
79,125,725✔
340
    terrno = TAOS_SYSTEM_ERROR(errno);
287✔
341
    taosReleaseConv(idx, conv, M2C);
287✔
UNCOV
342
    return false;
×
343
  }
344

345
  taosReleaseConv(idx, conv, M2C);
79,117,376✔
346
  if (len != NULL) {
79,192,705!
347
    *len = (int32_t)(ucs4_max_len - outLeft);
79,199,259✔
348
    if (*len < 0) {
79,199,259!
349
      // can not happen
350
      terrno = TSDB_CODE_APP_ERROR;
×
351
      return false;
×
352
    }
353
  }
354

355
  return true;
79,192,705✔
356
#endif
357
}
358

359
// if success, return the number of bytes written to mbs ( >= 0)
360
// otherwise return error code ( < 0)
361
int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs) {
314,224,685✔
362
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
363
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
364
  terrno = TSDB_CODE_APP_ERROR;
365
  return terrno;
366
#else
367

368
  int32_t idx = -1;
314,224,685✔
369
  int32_t code = 0;
314,224,685✔
370
  iconv_t conv = taosAcquireConv(&idx, C2M);
314,224,685✔
371
  if ((iconv_t)-1 == conv) {
314,430,139!
372
    return terrno;
×
373
  }
374
  
375
  size_t  ucs4_input_len = ucs4_max_len;
314,430,139✔
376
  size_t  outLen = ucs4_max_len;
314,430,139✔
377
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
314,430,139!
378
    code = TAOS_SYSTEM_ERROR(errno);
×
379
    taosReleaseConv(idx, conv, C2M);
×
380
    terrno = code;    
×
381
    return code;
4,209✔
382
  }
383
  
384
  taosReleaseConv(idx, conv, C2M);
314,316,676✔
385
  
386
  return (int32_t)(ucs4_max_len - outLen);
314,545,841✔
387
#endif
388
}
389

390
// if success, return the number of bytes written to mbs ( >= 0)
391
// otherwise return error code ( < 0)
392
int32_t taosUcs4ToMbsEx(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs, iconv_t conv) {
24,947,855✔
393
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
394
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
395
  terrno = TSDB_CODE_APP_ERROR;
396
  return terrno;
397
#else
398

399
  size_t ucs4_input_len = ucs4_max_len;
24,947,855✔
400
  size_t outLen = ucs4_max_len;
24,947,855✔
401
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
24,947,855!
402
    terrno = TAOS_SYSTEM_ERROR(errno);
×
403
    return terrno;
×
404
  }
405
  
406
  return (int32_t)(ucs4_max_len - outLen);
24,948,036✔
407
#endif
408
}
409

410
bool taosValidateEncodec(const char *encodec) {
8,998✔
411
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
412
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
413
  terrno = TSDB_CODE_APP_ERROR;
414
  return false;
415
#else
416
  iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC);
8,998✔
417
  if (cd == (iconv_t)(-1)) {
8,998!
418
    terrno = TAOS_SYSTEM_ERROR(errno);
×
419
    return false;
×
420
  }
421

422
  (void)iconv_close(cd);
8,998✔
423
  return true;
8,998✔
424
#endif
425
}
426

427
int32_t taosUcs4len(TdUcs4 *ucs4) {
×
428
  TdUcs4 *wstr = (TdUcs4 *)ucs4;
×
429
  if (NULL == wstr) {
×
430
    return 0;
×
431
  }
432

433
  int32_t n = 0;
×
434
  while (1) {
435
    if (0 == *wstr++) {
×
436
      break;
×
437
    }
438
    n++;
×
439
  }
440

441
  return n;
×
442
}
443

444
// dst buffer size should be at least 2*len + 1
445
int32_t taosHexEncode(const unsigned char *src, char *dst, int32_t len, int32_t bufSize) {
×
446
  if (!dst) {
×
447
    terrno = TSDB_CODE_INVALID_PARA;
×
448
    return terrno;
×
449
  }
450

451
  for (int32_t i = 0; i < len; ++i) {
×
452
    (void)snprintf(dst + i * 2, bufSize - i * 2, "%02x", src[i]);
×
453
  }
454

455
  return 0;
×
456
}
457

458
int32_t taosHexDecode(const char *src, char *dst, int32_t len) {
×
459
  if (!dst) {
×
460
    terrno = TSDB_CODE_INVALID_PARA;
×
461
    return terrno;
×
462
  }
463

464
  uint8_t hn, ln, out;
465
  for (int i = 0, j = 0; i < len * 2; i += 2, ++j) {
×
466
    hn = src[i] > '9' ? src[i] - 'a' + 10 : src[i] - '0';
×
467
    ln = src[i + 1] > '9' ? src[i + 1] - 'a' + 10 : src[i + 1] - '0';
×
468

469
    out = (hn << 4) | ln;
×
470
    (void)memcpy(dst + j, &out, 1);
×
471
  }
472

473
  return 0;
×
474
}
475

476
int32_t taosWcharWidth(TdWchar wchar) { return wcwidth(wchar); }
46,711,755✔
477

478
int32_t taosWcharsWidth(TdWchar *pWchar, int32_t size) { return wcswidth(pWchar, size); }
×
479

480
int32_t taosMbToWchar(TdWchar *pWchar, const char *pStr, int32_t size) { return mbtowc(pWchar, pStr, size); }
46,711,662✔
481

482
int32_t taosMbsToWchars(TdWchar *pWchars, const char *pStrs, int32_t size) { return mbstowcs(pWchars, pStrs, size); }
×
483

484
int32_t taosWcharToMb(char *pStr, TdWchar wchar) { return wctomb(pStr, wchar); }
×
485

486
char *taosStrCaseStr(const char *str, const char *pattern) {
6✔
487
  size_t i;
488

489
  if (!*pattern) return (char *)str;
6!
490

491
  for (; *str; str++) {
180✔
492
    if (toupper(*str) == toupper(*pattern)) {
174✔
493
      for (i = 1;; i++) {
24✔
494
        if (!pattern[i]) return (char *)str;
24!
495
        if (toupper(str[i]) != toupper(pattern[i])) break;
24!
496
      }
497
    }
498
  }
499
  return NULL;
6✔
500
}
501

502
int64_t taosStr2Int64(const char *str, char **pEnd, int32_t radix) {
1,220,952,609✔
503
  int64_t tmp = strtoll(str, pEnd, radix);
1,220,952,609✔
504
#if defined(DARWIN) || defined(_ALPINE)
505
  if (errno == EINVAL) errno = 0;
506
#endif
507
  return tmp;
1,271,187,472✔
508
}
509

510
uint64_t taosStr2UInt64(const char *str, char **pEnd, int32_t radix) {
165,080,340✔
511
  uint64_t tmp = strtoull(str, pEnd, radix);
165,080,340✔
512
#if defined(DARWIN) || defined(_ALPINE)
513
  if (errno == EINVAL) errno = 0;
514
#endif
515
  return tmp;
166,341,109✔
516
}
517

518
int32_t taosStr2Int32(const char *str, char **pEnd, int32_t radix) {
16,081,846✔
519
  int32_t tmp = strtol(str, pEnd, radix);
16,081,846✔
520
#if defined(DARWIN) || defined(_ALPINE)
521
  if (errno == EINVAL) errno = 0;
522
#endif
523
  return tmp;
16,087,151✔
524
}
525

526
uint32_t taosStr2UInt32(const char *str, char **pEnd, int32_t radix) {
7,137✔
527
  uint32_t tmp = strtol(str, pEnd, radix);
7,137✔
528
#if defined(DARWIN) || defined(_ALPINE)
529
  if (errno == EINVAL) errno = 0;
530
#endif
531
  return tmp;
7,138✔
532
}
533

534
int16_t taosStr2Int16(const char *str, char **pEnd, int32_t radix) {
34,930✔
535
  int32_t tmp = strtol(str, pEnd, radix);
34,930✔
536
#if defined(DARWIN) || defined(_ALPINE)
537
  if (errno == EINVAL) errno = 0;
538
#endif
539
  return (int16_t)tmp;
34,930✔
540
}
541

542
uint16_t taosStr2UInt16(const char *str, char **pEnd, int32_t radix) {
5,225✔
543
  uint32_t tmp = strtoul(str, pEnd, radix);
5,225✔
544
#if defined(DARWIN) || defined(_ALPINE)
545
  if (errno == EINVAL) errno = 0;
546
#endif
547
  return (uint16_t)tmp;
5,225✔
548
}
549

550
int8_t taosStr2Int8(const char *str, char **pEnd, int32_t radix) {
30,298✔
551
  int32_t tmp = strtol(str, pEnd, radix);
30,298✔
552
  return tmp;
30,298✔
553
}
554

555
uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix) {
5,899✔
556
  uint32_t tmp = strtoul(str, pEnd, radix);
5,899✔
557
#if defined(DARWIN) || defined(_ALPINE)
558
  if (errno == EINVAL) errno = 0;
559
#endif
560
  return tmp;
5,899✔
561
}
562

563
double taosStr2Double(const char *str, char **pEnd) {
166,239,279✔
564
  double tmp = strtod(str, pEnd);
166,239,279✔
565
  return tmp;
168,234,949✔
566
}
567

568
float taosStr2Float(const char *str, char **pEnd) {
29,219✔
569
  float tmp = strtof(str, pEnd);
29,219✔
570
  return tmp;
29,219✔
571
}
572

573
#define HEX_PREFIX_LEN 2  // \x
574
bool isHex(const char *z, uint32_t n) {
10,728,985✔
575
  if (n < HEX_PREFIX_LEN) return false;
10,728,985✔
576
  if (z[0] == '\\' && z[1] == 'x') return true;
10,628,763✔
577
  return false;
10,623,743✔
578
}
579

580
bool isValidateHex(const char *z, uint32_t n) {
5,020✔
581
  if ((n & 1) != 0) return false;
5,020✔
582
  for (size_t i = HEX_PREFIX_LEN; i < n; i++) {
642,563,197✔
583
    if (isxdigit(z[i]) == 0) {
642,558,212!
584
      return false;
×
585
    }
586
  }
587
  return true;
4,985✔
588
}
589

590
int32_t taosHex2Ascii(const char *z, uint32_t n, void **data, uint32_t *size) {
4,985✔
591
  n -= HEX_PREFIX_LEN;  // remove 0x
4,985✔
592
  z += HEX_PREFIX_LEN;
4,985✔
593
  *size = n / HEX_PREFIX_LEN;
4,985✔
594
  if (*size == 0) {
4,985✔
595
    if (!(*data = taosStrdup(""))) {
40!
596
      return terrno;
×
597
    }
598
    return 0;
40✔
599
  }
600
  
601
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size, 1);
4,945✔
602
  if (tmp == NULL) {
4,945!
603
    return terrno;
×
604
  }
605
  
606
  int8_t   num = 0;
4,945✔
607
  uint8_t *byte = tmp + *size - 1;
4,945✔
608

609
  for (int i = n - 1; i >= 0; i--) {
642,563,157✔
610
    if (z[i] >= 'a') {
642,558,212✔
611
      *byte |= ((uint8_t)(10 + (z[i] - 'a')) << (num * 4));
319,516,010✔
612
    } else if (z[i] >= 'A') {
323,042,202✔
613
      *byte |= ((uint8_t)(10 + (z[i] - 'A')) << (num * 4));
17✔
614
    } else {
615
      *byte |= ((uint8_t)(z[i] - '0') << (num * 4));
323,042,185✔
616
    }
617
    if (num == 1) {
642,558,212✔
618
      byte--;
321,279,106✔
619
      num = 0;
321,279,106✔
620
    } else {
621
      num++;
321,279,106✔
622
    }
623
  }
624
  *data = tmp;
4,945✔
625
  
626
  return 0;
4,945✔
627
}
628

629
// int32_t taosBin2Ascii(const char *z, uint32_t n, void** data, uint32_t* size){
630
//
631
//   for (i = 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) {
632
//   }
633
//
634
//   n -= 2;   // remove 0b
635
//   z += 2;
636
//   *size = n%8 == 0 ? n/8 : n/8 + 1;
637
//   uint8_t* tmp = (uint8_t*)taosMemoryCalloc(*size, 1);
638
//   if(tmp == NULL) return -1;
639
//   int8_t   num = 0;
640
//   uint8_t *byte = tmp + *size - 1;
641
//
642
//   for (int i = n - 1; i >= 0; i--) {
643
//     *byte |= ((uint8_t)(z[i] - '0') << num);
644
//     if (num == 7) {
645
//       byte--;
646
//       num = 0;
647
//     } else {
648
//       num++;
649
//     }
650
//   }
651
//   *data = tmp;
652
//   return 0;
653
// }
654

655
static char valueOf(uint8_t symbol) {
132,294✔
656
  switch (symbol) {
132,294!
657
    case 0:
131,092✔
658
      return '0';
131,092✔
659
    case 1:
36✔
660
      return '1';
36✔
661
    case 2:
64✔
662
      return '2';
64✔
663
    case 3:
19✔
664
      return '3';
19✔
665
    case 4:
363✔
666
      return '4';
363✔
667
    case 5:
228✔
668
      return '5';
228✔
669
    case 6:
65✔
670
      return '6';
65✔
671
    case 7:
13✔
672
      return '7';
13✔
673
    case 8:
18✔
674
      return '8';
18✔
675
    case 9:
9✔
676
      return '9';
9✔
677
    case 10:
12✔
678
      return 'A';
12✔
679
    case 11:
12✔
680
      return 'B';
12✔
681
    case 12:
233✔
682
      return 'C';
233✔
683
    case 13:
1✔
684
      return 'D';
1✔
685
    case 14:
116✔
686
      return 'E';
116✔
687
    case 15:
13✔
688
      return 'F';
13✔
689
    default: {
×
690
      return -1;
×
691
    }
692
  }
693
}
694

695
int32_t taosAscii2Hex(const char *z, uint32_t n, void **data, uint32_t *size) {
251✔
696
  *size = n * 2 + HEX_PREFIX_LEN;
251✔
697
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size + 1, 1);
251✔
698
  if (tmp == NULL) {
251!
699
    return terrno;
×
700
  }
701
  
702
  *data = tmp;
251✔
703
  *(tmp++) = '\\';
251✔
704
  *(tmp++) = 'x';
251✔
705
  for (int i = 0; i < n; i++) {
66,398✔
706
    uint8_t val = z[i];
66,147✔
707
    tmp[i * 2] = valueOf(val >> 4);
66,147✔
708
    tmp[i * 2 + 1] = valueOf(val & 0x0F);
66,147✔
709
  }
710
  
711
  return 0;
251✔
712
}
713

714
int64_t tsnprintf(char *dst, int64_t size, const char *format, ...) {
662,334,680✔
715
  if (size <= 0) return 0;
662,334,680!
716
  if (size == 1) {
662,334,680!
717
    dst[0] = '\0';
×
718
    return 0;
×
719
  }
720
  if (size > SIZE_MAX) {
721
    size = SIZE_MAX;
722
  }
723

724
  int64_t ret;
725
  va_list args;
726
  va_start(args, format);
662,334,680✔
727
  ret = vsnprintf(dst, size, format, args);
662,334,680✔
728
  va_end(args);
662,334,680✔
729
  if (ret >= size) {
662,334,680✔
730
    return size - 1;
2,416✔
731
  } else {
732
    return ret;
662,332,264✔
733
  }
734
}
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