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

taosdata / TDengine / #3543

29 Nov 2024 02:58AM UTC coverage: 60.842% (+0.02%) from 60.819%
#3543

push

travis-ci

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

merge: from main to 3.0

120460 of 253224 branches covered (47.57%)

Branch coverage included in aggregate %.

706 of 908 new or added lines in 18 files covered. (77.75%)

2401 existing lines in 137 files now uncovered.

201633 of 276172 relevant lines covered (73.01%)

19045673.23 hits per line

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

57.14
/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) {
143,002,617✔
28
  if (str == NULL) {
143,002,617!
29
    terrno = TSDB_CODE_INVALID_PARA;
×
30
    return NULL;
×
31
  }
32
#ifdef WINDOWS
33
  return _strdup(str);
34
#else
35
  char *p = strdup(str);
143,002,617✔
36
  if (NULL == p) {
143,002,617!
37
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
38
  }
39
  return p;
143,002,617✔
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 *taosStrndup(const char *s, int 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
#else
107
char *taosStrndup(const char *s, int size) {
196,908,286✔
108
  if (s == NULL) {
196,908,286!
109
    return NULL;
×
110
  }
111
  char *p = strndup(s, size);
196,908,286✔
112
  if (NULL == p) {
196,908,286!
113
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
114
  }
115
  return p;
196,908,286✔
116
}
117
#endif
118

119
int32_t taosStr2int64(const char *str, int64_t *val) {
339✔
120
  if (str == NULL || val == NULL) {
339!
121
    return TSDB_CODE_INVALID_PARA;
×
122
  }
123
  char   *endptr = NULL;
339✔
124
  int64_t ret = strtoll(str, &endptr, 10);
339✔
125
  if (errno == ERANGE && (ret == LLONG_MAX || ret == LLONG_MIN)) {
340!
126
    return TAOS_SYSTEM_ERROR(errno);
×
127
  } else if (errno == EINVAL && ret == 0) {
340!
128
    return TSDB_CODE_INVALID_PARA;
×
129
  } else {
130
    *val = ret;
340✔
131
    return 0;
340✔
132
  }
133
}
134

135
int32_t taosStr2int16(const char *str, int16_t *val) {
×
136
  OS_PARAM_CHECK(str);
×
137
  OS_PARAM_CHECK(val);
×
138
  int64_t tmp = 0;
×
139
  int32_t code = taosStr2int64(str, &tmp);
×
140
  if (code) {
×
141
    return code;
×
142
  } else if (tmp > INT16_MAX || tmp < INT16_MIN) {
×
143
    return TAOS_SYSTEM_ERROR(ERANGE);
×
144
  } else {
145
    *val = (int16_t)tmp;
×
146
    return 0;
×
147
  }
148
}
149

150
int32_t taosStr2int32(const char *str, int32_t *val) {
42✔
151
  OS_PARAM_CHECK(str);
42!
152
  OS_PARAM_CHECK(val);
42!
153
  int64_t tmp = 0;
42✔
154
  int32_t code = taosStr2int64(str, &tmp);
42✔
155
  if (code) {
42!
156
    return code;
×
157
  } else if (tmp > INT32_MAX || tmp < INT32_MIN) {
42!
158
    return TAOS_SYSTEM_ERROR(ERANGE);
×
159
  } else {
160
    *val = (int32_t)tmp;
42✔
161
    return 0;
42✔
162
  }
163
}
164

165
int32_t taosStr2int8(const char *str, int8_t *val) {
×
166
  OS_PARAM_CHECK(str);
×
167
  OS_PARAM_CHECK(val);
×
168
  int64_t tmp = 0;
×
169
  int32_t code = taosStr2int64(str, &tmp);
×
170
  if (code) {
×
171
    return code;
×
172
  } else if (tmp > INT8_MAX || tmp < INT8_MIN) {
×
173
    return TAOS_SYSTEM_ERROR(ERANGE);
×
174
  } else {
175
    *val = (int8_t)tmp;
×
176
    return 0;
×
177
  }
178
}
179

180
int32_t tasoUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes) {
182,917,282✔
181
  if ((f1_ucs4 == NULL || f2_ucs4 == NULL)) {
182,917,282!
182
    return TSDB_CODE_INVALID_PARA;
×
183
  }
184
  for (int32_t i = 0; i < bytes; i += sizeof(TdUcs4)) {
796,768,136✔
185
    int32_t f1 = *(int32_t *)((char *)f1_ucs4 + i);
740,415,955✔
186
    int32_t f2 = *(int32_t *)((char *)f2_ucs4 + i);
740,415,955✔
187

188
    if ((f1 == 0 && f2 != 0) || (f1 != 0 && f2 == 0)) {
740,415,955!
189
      return f1 - f2;
×
190
    } else if (f1 == 0 && f2 == 0) {
740,415,955!
191
      return 0;
×
192
    }
193

194
    if (f1 != f2) {
740,415,955✔
195
      return f1 - f2;
126,679,889✔
196
    }
197
  }
198

199
  return 0;
56,352,181✔
200

201
  //#if 0
202
  //  int32_t ucs4_max_len = bytes + 4;
203
  //  char *f1_mbs = taosMemoryCalloc(bytes, 1);
204
  //  char *f2_mbs = taosMemoryCalloc(bytes, 1);
205
  //  if (taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs) < 0) {
206
  //    return -1;
207
  //  }
208
  //  if (taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs) < 0) {
209
  //    return -1;
210
  //  }
211
  //  int32_t ret = strcmp(f1_mbs, f2_mbs);
212
  //  taosMemoryFree(f1_mbs);
213
  //  taosMemoryFree(f2_mbs);
214
  //  return ret;
215
  //#endif
216
}
217

218
int32_t tasoUcs4Copy(TdUcs4 *target_ucs4, TdUcs4 *source_ucs4, int32_t len_ucs4) {
×
219
  if (target_ucs4 == NULL || source_ucs4 == NULL || len_ucs4 <= 0) {
×
220
    return TSDB_CODE_INVALID_PARA;
×
221
  }
222
  if (taosMemorySize(target_ucs4) < len_ucs4 * sizeof(TdUcs4)) {
×
223
    terrno = TSDB_CODE_INVALID_PARA;
×
224
    return terrno;
×
225
  }
226
  
227
  (void)memcpy(target_ucs4, source_ucs4, len_ucs4 * sizeof(TdUcs4));
×
228

229
  return TSDB_CODE_SUCCESS;
×
230
}
231

232
typedef struct {
233
  iconv_t conv;
234
  int8_t  inUse;
235
} SConv;
236

237
// 0: Mbs --> Ucs4
238
// 1: Ucs4--> Mbs
239
SConv  *gConv[2] = {NULL, NULL};
240
int32_t convUsed[2] = {0, 0};
241
int32_t gConvMaxNum[2] = {0, 0};
242

243
int32_t taosConvInit(void) {
6,568✔
244
  int8_t M2C = 0;
6,568✔
245
  gConvMaxNum[M2C] = 512;
6,568✔
246
  gConvMaxNum[1 - M2C] = 512;
6,568✔
247

248
  gConv[M2C] = taosMemoryCalloc(gConvMaxNum[M2C], sizeof(SConv));
6,568✔
249
  if (gConv[M2C] == NULL) {
6,568!
250
    return terrno;
×
251
  }
252

253
  gConv[1 - M2C] = taosMemoryCalloc(gConvMaxNum[1 - M2C], sizeof(SConv));
6,568✔
254
  if (gConv[1 - M2C] == NULL) {
6,568!
255
    taosMemoryFree(gConv[M2C]);
×
256
    return terrno;
×
257
  }
258

259
  for (int32_t i = 0; i < gConvMaxNum[M2C]; ++i) {
3,369,384✔
260
    gConv[M2C][i].conv = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset);
3,362,816✔
261
    if ((iconv_t)-1 == gConv[M2C][i].conv) {
3,362,816!
262
      terrno = TAOS_SYSTEM_ERROR(errno);
×
263
      return terrno;
×
264
    }
265
  }
266
  for (int32_t i = 0; i < gConvMaxNum[1 - M2C]; ++i) {
3,369,384✔
267
    gConv[1 - M2C][i].conv = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC);
3,362,816✔
268
    if ((iconv_t)-1 == gConv[1 - M2C][i].conv) {
3,362,816!
269
      terrno = TAOS_SYSTEM_ERROR(errno);
×
270
      return terrno;
×
271
    }
272
  }
273

274
  return 0;
6,568✔
275
}
276

277
void taosConvDestroy() {
6,567✔
278
  int8_t M2C = 0;
6,567✔
279
  for (int32_t i = 0; i < gConvMaxNum[M2C]; ++i) {
3,368,871✔
280
    (void)iconv_close(gConv[M2C][i].conv);
3,362,304✔
281
  }
282
  for (int32_t i = 0; i < gConvMaxNum[1 - M2C]; ++i) {
3,368,871✔
283
    (void)iconv_close(gConv[1 - M2C][i].conv);
3,362,304✔
284
  }
285
  taosMemoryFreeClear(gConv[M2C]);
6,567!
286
  taosMemoryFreeClear(gConv[1 - M2C]);
6,567!
287
  gConvMaxNum[M2C] = -1;
6,567✔
288
  gConvMaxNum[1 - M2C] = -1;
6,567✔
289
}
6,567✔
290

291
iconv_t taosAcquireConv(int32_t *idx, ConvType type) {
369,867,448✔
292
  if(idx == NULL) {
369,867,448!
293
    terrno = TSDB_CODE_INVALID_PARA;
×
294
    return (iconv_t)-1;
×
295
  }
296
  if (gConvMaxNum[type] <= 0) {
369,867,448!
297
    *idx = -1;
×
298
    if (type == M2C) {
×
299
      iconv_t c = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset);
×
300
      if ((iconv_t)-1 == c) {
×
301
        terrno = TAOS_SYSTEM_ERROR(errno);
×
302
      }
303
      return c;
×
304
    } else {
305
      iconv_t c = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC);
×
306
      if ((iconv_t)-1 == c) {
×
307
        terrno = TAOS_SYSTEM_ERROR(errno);
×
308
      }
309
      return c;
×
310
    }
311
  }
312

313
  while (true) {
×
314
    int32_t used = atomic_add_fetch_32(&convUsed[type], 1);
369,867,448✔
315
    if (used > gConvMaxNum[type]) {
370,328,227!
316
      used = atomic_sub_fetch_32(&convUsed[type], 1);
×
317
      (void)sched_yield();
×
318
      continue;
×
319
    }
320

321
    break;
370,358,394✔
322
  }
323

324
  int32_t startId = taosGetSelfPthreadId() % gConvMaxNum[type];
370,358,394✔
325
  while (true) {
9,449✔
326
    if (gConv[type][startId].inUse) {
370,228,737✔
327
      startId = (startId + 1) % gConvMaxNum[type];
184✔
328
      continue;
184✔
329
    }
330

331
    int8_t old = atomic_val_compare_exchange_8(&gConv[type][startId].inUse, 0, 1);
370,228,553✔
332
    if (0 == old) {
370,381,430✔
333
      break;
370,372,165✔
334
    }
335
  }
336

337
  *idx = startId;
370,372,165✔
338
  if ((iconv_t)0 == gConv[type][startId].conv) {
370,372,165!
339
    return (iconv_t)-1;
×
340
  } else {
341
    return gConv[type][startId].conv;
370,372,165✔
342
  }
343
}
344

345
void taosReleaseConv(int32_t idx, iconv_t conv, ConvType type) {
370,064,529✔
346
  if (idx < 0) {
370,064,529!
347
    (void)iconv_close(conv);
×
348
    return;
×
349
  }
350

351
  atomic_store_8(&gConv[type][idx].inUse, 0);
370,064,529✔
352
  (void)atomic_sub_fetch_32(&convUsed[type], 1);
370,381,736✔
353
}
354

355
bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len) {
72,875,219✔
356
  if (ucs4_max_len == 0) {
72,875,219✔
357
    return true;
481,325✔
358
  }
359
  if(ucs4_max_len < 0 || mbs == NULL || ucs4 == NULL) {
72,393,894!
360
    terrno = TSDB_CODE_INVALID_PARA;
×
361
    return false;
×
362
  }
363
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
364
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
365
  terrno = TSDB_CODE_APP_ERROR;
366
  return false;
367
#else
368
  (void)memset(ucs4, 0, ucs4_max_len);
72,420,328✔
369

370
  int32_t idx = -1;
72,420,328✔
371
  iconv_t conv = taosAcquireConv(&idx, M2C);
72,420,328✔
372
  if ((iconv_t)-1 == conv) {
72,640,489!
373
    return false;
×
374
  }
375
  
376
  size_t  ucs4_input_len = mbsLength;
72,640,489✔
377
  size_t  outLeft = ucs4_max_len;
72,640,489✔
378
  if (iconv(conv, (char **)&mbs, &ucs4_input_len, (char **)&ucs4, &outLeft) == -1) {
72,640,489✔
379
    terrno = TAOS_SYSTEM_ERROR(errno);
287✔
380
    taosReleaseConv(idx, conv, M2C);
287✔
UNCOV
381
    return false;
×
382
  }
383

384
  taosReleaseConv(idx, conv, M2C);
72,627,491✔
385
  if (len != NULL) {
72,763,074✔
386
    *len = (int32_t)(ucs4_max_len - outLeft);
72,733,669✔
387
    if (*len < 0) {
72,733,669!
388
      // can not happen
389
      terrno = TSDB_CODE_APP_ERROR;
×
390
      return false;
×
391
    }
392
  }
393

394
  return true;
72,763,074✔
395
#endif
396
}
397

398
// if success, return the number of bytes written to mbs ( >= 0)
399
// otherwise return error code ( < 0)
400
int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs) {
296,124,593✔
401
  if (ucs4_max_len == 0) {
296,124,593✔
402
    return 0;
116✔
403
  }
404
  if(ucs4_max_len < 0 || ucs4 == NULL || mbs == NULL) {
296,124,477!
405
    terrno = TSDB_CODE_INVALID_PARA;
×
406
    return terrno;
×
407
  }
408
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
409
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
410
  terrno = TSDB_CODE_APP_ERROR;
411
  return terrno;
412
#else
413

414
  int32_t idx = -1;
296,133,015✔
415
  int32_t code = 0;
296,133,015✔
416
  iconv_t conv = taosAcquireConv(&idx, C2M);
296,133,015✔
417
  if ((iconv_t)-1 == conv) {
296,250,089!
418
    return terrno;
×
419
  }
420
  
421
  size_t  ucs4_input_len = ucs4_max_len;
296,250,089✔
422
  size_t  outLen = ucs4_max_len;
296,250,089✔
423
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
296,250,089!
424
    code = TAOS_SYSTEM_ERROR(errno);
×
425
    taosReleaseConv(idx, conv, C2M);
×
426
    terrno = code;    
×
427
    return code;
1,807✔
428
  }
429
  
430
  taosReleaseConv(idx, conv, C2M);
296,206,161✔
431
  
432
  return (int32_t)(ucs4_max_len - outLen);
296,307,610✔
433
#endif
434
}
435

436
// if success, return the number of bytes written to mbs ( >= 0)
437
// otherwise return error code ( < 0)
438
int32_t taosUcs4ToMbsEx(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs, iconv_t conv) {
24,382,522✔
439
  if (ucs4_max_len == 0) {
24,382,522✔
440
    return 0;
57,999✔
441
  }
442
  if(ucs4_max_len < 0 || ucs4 == NULL || mbs == NULL) {
24,324,523!
443
    terrno = TSDB_CODE_INVALID_PARA;
×
444
    return terrno;
×
445
  }
446
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
447
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
448
  terrno = TSDB_CODE_APP_ERROR;
449
  return terrno;
450
#else
451

452
  size_t ucs4_input_len = ucs4_max_len;
24,324,528✔
453
  size_t outLen = ucs4_max_len;
24,324,528✔
454
  if (iconv(conv, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
24,324,528!
455
    terrno = TAOS_SYSTEM_ERROR(errno);
×
456
    return terrno;
×
457
  }
458
  
459
  return (int32_t)(ucs4_max_len - outLen);
24,324,579✔
460
#endif
461
}
462

463
bool taosValidateEncodec(const char *encodec) {
9,141✔
464
  if(encodec == NULL) {
9,141!
465
    terrno = TSDB_CODE_INVALID_PARA;
×
466
    return false;
×
467
  }
468
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
469
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n");
470
  terrno = TSDB_CODE_APP_ERROR;
471
  return false;
472
#else
473
  iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC);
9,141✔
474
  if (cd == (iconv_t)(-1)) {
9,141!
475
    terrno = TAOS_SYSTEM_ERROR(errno);
×
476
    return false;
×
477
  }
478

479
  (void)iconv_close(cd);
9,141✔
480
  return true;
9,141✔
481
#endif
482
}
483

484
int32_t taosUcs4len(TdUcs4 *ucs4) {
×
485
  TdUcs4 *wstr = (TdUcs4 *)ucs4;
×
486
  if (NULL == wstr) {
×
487
    return 0;
×
488
  }
489

490
  int32_t n = 0;
×
491
  while (1) {
492
    if (0 == *wstr++) {
×
493
      break;
×
494
    }
495
    n++;
×
496
  }
497

498
  return n;
×
499
}
500

501
// dst buffer size should be at least 2*len + 1
502
int32_t taosHexEncode(const unsigned char *src, char *dst, int32_t len, int32_t bufSize) {
×
503
  if (!dst || !src || bufSize <= 0) {
×
504
    terrno = TSDB_CODE_INVALID_PARA;
×
505
    return terrno;
×
506
  }
507

508
  for (int32_t i = 0; i < len; ++i) {
×
509
    (void)snprintf(dst + i * 2, bufSize - i * 2, "%02x", src[i]);
×
510
  }
511

512
  return 0;
×
513
}
514

515
int32_t taosHexDecode(const char *src, char *dst, int32_t len) {
×
516
  if(!src || !dst || len <= 0) {
×
517
    terrno = TSDB_CODE_INVALID_PARA;
×
518
    return terrno;
×
519
  }
520

521
  uint8_t hn, ln, out;
522
  for (int i = 0, j = 0; i < len * 2; i += 2, ++j) {
×
523
    hn = src[i] > '9' ? src[i] - 'a' + 10 : src[i] - '0';
×
524
    ln = src[i + 1] > '9' ? src[i + 1] - 'a' + 10 : src[i + 1] - '0';
×
525

526
    out = (hn << 4) | ln;
×
527
    (void)memcpy(dst + j, &out, 1);
×
528
  }
529

530
  return 0;
×
531
}
532

533
int32_t taosWcharWidth(TdWchar wchar) { return wcwidth(wchar); }
42,210,879✔
534

535
int32_t taosWcharsWidth(TdWchar *pWchar, int32_t size) {
×
536
  if (pWchar == NULL || size <= 0) {
×
537
    terrno = TSDB_CODE_INVALID_PARA;
×
538
    return terrno;
×
539
  }
540
  return wcswidth(pWchar, size);
×
541
}
542

543
int32_t taosMbToWchar(TdWchar *pWchar, const char *pStr, int32_t size) {
42,210,786✔
544
  if (pWchar == NULL || pStr == NULL || size <= 0) {
42,210,786!
545
    terrno = TSDB_CODE_INVALID_PARA;
×
546
    return terrno;
×
547
  }
548
  return mbtowc(pWchar, pStr, size);
42,210,786✔
549
}
550

551
int32_t taosMbsToWchars(TdWchar *pWchars, const char *pStrs, int32_t size) {
×
552
  if (pWchars == NULL || pStrs == NULL || size <= 0) {
×
553
    terrno = TSDB_CODE_INVALID_PARA;
×
554
    return terrno;
×
555
  }
556
  return mbstowcs(pWchars, pStrs, size);
×
557
}
558

559
int32_t taosWcharToMb(char *pStr, TdWchar wchar) { 
×
560
  OS_PARAM_CHECK(pStr);
×
561
  return wctomb(pStr, wchar); }
×
562

563
char *taosStrCaseStr(const char *str, const char *pattern) {
6✔
564
  if (str == NULL) {
6!
565
    terrno = TSDB_CODE_INVALID_PARA;
×
566
    return NULL;
×
567
  }
568
  if (!pattern || !*pattern) return (char *)str;
6!
569

570
  size_t i;
571
  for (; *str; str++) {
180✔
572
    if (toupper(*str) == toupper(*pattern)) {
174✔
573
      for (i = 1;; i++) {
24✔
574
        if (!pattern[i]) return (char *)str;
24!
575
        if (toupper(str[i]) != toupper(pattern[i])) break;
24!
576
      }
577
    }
578
  }
579
  return NULL;
6✔
580
}
581

582
int64_t taosStr2Int64(const char *str, char **pEnd, int32_t radix) {
2,070,811,226✔
583
  if(str == NULL) {
2,070,811,226!
584
    terrno = TSDB_CODE_INVALID_PARA;
×
585
    return 0;
×
586
  }
587
  int64_t tmp = strtoll(str, pEnd, radix);
2,070,811,226✔
588
#if defined(DARWIN) || defined(_ALPINE)
589
  if (errno == EINVAL) errno = 0;
590
#endif
591
  return tmp;
2,122,767,006✔
592
}
593

594
uint64_t taosStr2UInt64(const char *str, char **pEnd, int32_t radix) {
165,923,104✔
595
  if(str == NULL) {
165,923,104!
596
    terrno = TSDB_CODE_INVALID_PARA;
×
597
    return 0;
×
598
  }
599
  uint64_t tmp = strtoull(str, pEnd, radix);
165,923,104✔
600
#if defined(DARWIN) || defined(_ALPINE)
601
  if (errno == EINVAL) errno = 0;
602
#endif
603
  return tmp;
167,761,796✔
604
}
605

606
int32_t taosStr2Int32(const char *str, char **pEnd, int32_t radix) {
18,997,033✔
607
  if(str == NULL) {
18,997,033!
608
    terrno = TSDB_CODE_INVALID_PARA;
×
609
    return 0;
×
610
  }
611
  int32_t tmp = strtol(str, pEnd, radix);
18,997,033✔
612
#if defined(DARWIN) || defined(_ALPINE)
613
  if (errno == EINVAL) errno = 0;
614
#endif
615
  return tmp;
19,003,315✔
616
}
617

618
uint32_t taosStr2UInt32(const char *str, char **pEnd, int32_t radix) {
7,053✔
619
  if(str == NULL) {
7,053!
620
    terrno = TSDB_CODE_INVALID_PARA;
×
621
    return 0;
×
622
  }
623
  uint32_t tmp = strtol(str, pEnd, radix);
7,053✔
624
#if defined(DARWIN) || defined(_ALPINE)
625
  if (errno == EINVAL) errno = 0;
626
#endif
627
  return tmp;
7,054✔
628
}
629

630
int16_t taosStr2Int16(const char *str, char **pEnd, int32_t radix) {
14,858✔
631
  if(str == NULL) {
14,858!
632
    terrno = TSDB_CODE_INVALID_PARA;
×
633
    return 0;
×
634
  }
635
  int32_t tmp = strtol(str, pEnd, radix);
14,858✔
636
#if defined(DARWIN) || defined(_ALPINE)
637
  if (errno == EINVAL) errno = 0;
638
#endif
639
  return (int16_t)tmp;
14,858✔
640
}
641

642
uint16_t taosStr2UInt16(const char *str, char **pEnd, int32_t radix) {
5,357✔
643
  if(str == NULL) {
5,357!
644
    terrno = TSDB_CODE_INVALID_PARA;
×
645
    return 0;
×
646
  }
647
  uint32_t tmp = strtoul(str, pEnd, radix);
5,357✔
648
#if defined(DARWIN) || defined(_ALPINE)
649
  if (errno == EINVAL) errno = 0;
650
#endif
651
  return (uint16_t)tmp;
5,357✔
652
}
653

654
int8_t taosStr2Int8(const char *str, char **pEnd, int32_t radix) {
37,422✔
655
  if(str == NULL) {
37,422!
656
    terrno = TSDB_CODE_INVALID_PARA;
×
657
    return 0;
×
658
  }
659
  int32_t tmp = strtol(str, pEnd, radix);
37,422✔
660
  return tmp;
37,422✔
661
}
662

663
uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix) {
6,030✔
664
  if(str == NULL) {
6,030!
665
    terrno = TSDB_CODE_INVALID_PARA;
×
666
    return 0;
×
667
  }
668
  uint32_t tmp = strtoul(str, pEnd, radix);
6,030✔
669
#if defined(DARWIN) || defined(_ALPINE)
670
  if (errno == EINVAL) errno = 0;
671
#endif
672
  return tmp;
6,030✔
673
}
674

675
double taosStr2Double(const char *str, char **pEnd) {
1,006,803,660✔
676
  if(str == NULL) {
1,006,803,660!
677
    terrno = TSDB_CODE_INVALID_PARA;
×
678
    return 0;
×
679
  }
680
  double tmp = strtod(str, pEnd);
1,006,803,660✔
681
  return tmp;
1,009,229,196✔
682
}
683

684
float taosStr2Float(const char *str, char **pEnd) {
25,029✔
685
  if(str == NULL) {
25,029!
686
    terrno = TSDB_CODE_INVALID_PARA;
×
687
    return 0;
×
688
  }
689
  float tmp = strtof(str, pEnd);
25,029✔
690
  return tmp;
25,029✔
691
}
692

693
#define HEX_PREFIX_LEN 2  // \x
694
bool isHex(const char *z, uint32_t n) {
10,664,977✔
695
  if (n < HEX_PREFIX_LEN) return false;
10,664,977✔
696
  if (z[0] == '\\' && z[1] == 'x') return true;
10,564,755✔
697
  return false;
10,559,735✔
698
}
699

700
bool isValidateHex(const char *z, uint32_t n) {
5,020✔
701
  if(!z) {
5,020!
702
    terrno = TSDB_CODE_INVALID_PARA;
×
703
    return false;
×
704
  }
705
  if ((n & 1) != 0) return false;
5,020✔
706
  for (size_t i = HEX_PREFIX_LEN; i < n; i++) {
642,563,197✔
707
    if (isxdigit(z[i]) == 0) {
642,558,212!
708
      return false;
×
709
    }
710
  }
711
  return true;
4,985✔
712
}
713

714
int32_t taosHex2Ascii(const char *z, uint32_t n, void **data, uint32_t *size) {
4,985✔
715
  OS_PARAM_CHECK(z);
4,985!
716
  OS_PARAM_CHECK(data);
4,985!
717
  OS_PARAM_CHECK(size);
4,985!
718
  n -= HEX_PREFIX_LEN;  // remove 0x
4,985✔
719
  z += HEX_PREFIX_LEN;
4,985✔
720
  *size = n / HEX_PREFIX_LEN;
4,985✔
721
  if (*size == 0) {
4,985✔
722
    if (!(*data = taosStrdup(""))) {
40!
723
      return terrno;
×
724
    }
725
    return 0;
40✔
726
  }
727
  
728
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size, 1);
4,945✔
729
  if (tmp == NULL) {
4,945!
730
    return terrno;
×
731
  }
732
  
733
  int8_t   num = 0;
4,945✔
734
  uint8_t *byte = tmp + *size - 1;
4,945✔
735

736
  for (int i = n - 1; i >= 0; i--) {
642,563,157✔
737
    if (z[i] >= 'a') {
642,558,212✔
738
      *byte |= ((uint8_t)(10 + (z[i] - 'a')) << (num * 4));
5,052,928✔
739
    } else if (z[i] >= 'A') {
637,505,284✔
740
      *byte |= ((uint8_t)(10 + (z[i] - 'A')) << (num * 4));
17✔
741
    } else {
742
      *byte |= ((uint8_t)(z[i] - '0') << (num * 4));
637,505,267✔
743
    }
744
    if (num == 1) {
642,558,212✔
745
      byte--;
321,279,106✔
746
      num = 0;
321,279,106✔
747
    } else {
748
      num++;
321,279,106✔
749
    }
750
  }
751
  *data = tmp;
4,945✔
752
  
753
  return 0;
4,945✔
754
}
755

756
// int32_t taosBin2Ascii(const char *z, uint32_t n, void** data, uint32_t* size){
757
//
758
//   for (i = 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) {
759
//   }
760
//
761
//   n -= 2;   // remove 0b
762
//   z += 2;
763
//   *size = n%8 == 0 ? n/8 : n/8 + 1;
764
//   uint8_t* tmp = (uint8_t*)taosMemoryCalloc(*size, 1);
765
//   if(tmp == NULL) return -1;
766
//   int8_t   num = 0;
767
//   uint8_t *byte = tmp + *size - 1;
768
//
769
//   for (int i = n - 1; i >= 0; i--) {
770
//     *byte |= ((uint8_t)(z[i] - '0') << num);
771
//     if (num == 7) {
772
//       byte--;
773
//       num = 0;
774
//     } else {
775
//       num++;
776
//     }
777
//   }
778
//   *data = tmp;
779
//   return 0;
780
// }
781

782
static char valueOf(uint8_t symbol) {
2,405,800✔
783
  switch (symbol) {
2,405,800!
784
    case 0:
175,501✔
785
      return '0';
175,501✔
786
    case 1:
79,974✔
787
      return '1';
79,974✔
788
    case 2:
84,442✔
789
      return '2';
84,442✔
790
    case 3:
102,158✔
791
      return '3';
102,158✔
792
    case 4:
111,386✔
793
      return '4';
111,386✔
794
    case 5:
106,809✔
795
      return '5';
106,809✔
796
    case 6:
728,329✔
797
      return '6';
728,329✔
798
    case 7:
608,383✔
799
      return '7';
608,383✔
800
    case 8:
66,634✔
801
      return '8';
66,634✔
802
    case 9:
88,829✔
803
      return '9';
88,829✔
804
    case 10:
57,744✔
805
      return 'A';
57,744✔
806
    case 11:
26,658✔
807
      return 'B';
26,658✔
808
    case 12:
35,763✔
809
      return 'C';
35,763✔
810
    case 13:
39,969✔
811
      return 'D';
39,969✔
812
    case 14:
48,968✔
813
      return 'E';
48,968✔
814
    case 15:
44,425✔
815
      return 'F';
44,425✔
816
    default: {
×
817
      return -1;
×
818
    }
819
  }
820
}
821

822
int32_t taosAscii2Hex(const char *z, uint32_t n, void **data, uint32_t *size) {
4,694✔
823
  *size = n * 2 + HEX_PREFIX_LEN;
4,694✔
824
  uint8_t *tmp = (uint8_t *)taosMemoryCalloc(*size + 1, 1);
4,694✔
825
  if (tmp == NULL) {
4,694!
826
    return terrno;
×
827
  }
828
  
829
  *data = tmp;
4,694✔
830
  *(tmp++) = '\\';
4,694✔
831
  *(tmp++) = 'x';
4,694✔
832
  for (int i = 0; i < n; i++) {
1,207,596✔
833
    uint8_t val = z[i];
1,202,902✔
834
    tmp[i * 2] = valueOf(val >> 4);
1,202,902✔
835
    tmp[i * 2 + 1] = valueOf(val & 0x0F);
1,202,905✔
836
  }
837
  
838
  return 0;
4,694✔
839
}
840

841
int64_t tsnprintf(char *dst, int64_t size, const char *format, ...) {
686,037,825✔
842
  if (dst == NULL || format == NULL) {
686,037,825!
843
    terrno = TSDB_CODE_INVALID_PARA;
×
844
    return 0;
×
845
  }
846
  if (size <= 0) return 0;
700,609,100!
847
  if (size == 1) {
700,609,100!
848
    dst[0] = '\0';
×
849
    return 0;
×
850
  }
851
  if (size > SIZE_MAX) {
852
    size = SIZE_MAX;
853
  }
854

855
  int64_t ret;
856
  va_list args;
857
  va_start(args, format);
700,609,100✔
858
  ret = vsnprintf(dst, size, format, args);
700,609,100✔
859
  va_end(args);
700,609,100✔
860
  if (ret >= size) {
700,609,100✔
861
    return size - 1;
1,274✔
862
  } else {
863
    return ret;
700,607,826✔
864
  }
865
}
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

© 2025 Coveralls, Inc