osString.c 10.2 KB
Newer Older
S
Shengliang Guan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

wafwerar's avatar
wafwerar 已提交
16
#define ALLOW_FORBID_FUNC
S
Shengliang Guan 已提交
17 18 19
#define _DEFAULT_SOURCE
#include "os.h"

wafwerar's avatar
wafwerar 已提交
20 21 22
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
#include "iconv.h"
#endif
S
Shengliang Guan 已提交
23

wafwerar's avatar
wafwerar 已提交
24 25 26
extern int wcwidth(wchar_t c);
extern int wcswidth(const wchar_t *s, size_t n);

wafwerar's avatar
wafwerar 已提交
27 28 29 30 31
#ifdef WINDOWS
char *strsep(char **stringp, const char *delim) {
  char *      s;
  const char *spanp;
  int32_t     c, sc;
dengyihao's avatar
dengyihao 已提交
32 33
  char *      tok;
  if ((s = *stringp) == NULL) return (NULL);
wafwerar's avatar
wafwerar 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
  for (tok = s;;) {
    c = *s++;
    spanp = delim;
    do {
      if ((sc = *spanp++) == c) {
        if (c == 0)
          s = NULL;
        else
          s[-1] = 0;
        *stringp = s;
        return (tok);
      }
    } while (sc != 0);
  }
  /* NOTREACHED */
}
/* Duplicate a string, up to at most size characters */
char *strndup(const char *s, size_t size) {
  size_t l;
dengyihao's avatar
dengyihao 已提交
53
  char * s2;
wafwerar's avatar
wafwerar 已提交
54
  l = strlen(s);
dengyihao's avatar
dengyihao 已提交
55 56
  if (l > size) l = size;
  s2 = malloc(l + 1);
wafwerar's avatar
wafwerar 已提交
57 58 59 60 61 62 63 64
  if (s2) {
    strncpy(s2, s, l);
    s2[l] = '\0';
  }
  return s2;
}
/* Copy no more than N characters of SRC to DEST, returning the address of
   the terminating '\0' in DEST, if any, or else DEST + N.  */
dengyihao's avatar
dengyihao 已提交
65 66 67
char *stpncpy(char *dest, const char *src, size_t n) {
  size_t size = strnlen(src, n);
  memcpy(dest, src, size);
wafwerar's avatar
wafwerar 已提交
68
  dest += size;
dengyihao's avatar
dengyihao 已提交
69 70
  if (size == n) return dest;
  return memset(dest, '\0', n - size);
wafwerar's avatar
wafwerar 已提交
71 72 73
}
#endif

74
int64_t taosStr2int64(const char *str) {
S
Shengliang Guan 已提交
75 76 77 78
  char *endptr = NULL;
  return strtoll(str, &endptr, 10);
}

wafwerar's avatar
wafwerar 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
int32_t tasoUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes) {
  for (int32_t i = 0; i < bytes; i += sizeof(TdUcs4)) {
    int32_t f1 = *(int32_t *)((char *)f1_ucs4 + i);
    int32_t f2 = *(int32_t *)((char *)f2_ucs4 + i);

    if ((f1 == 0 && f2 != 0) || (f1 != 0 && f2 == 0)) {
      return f1 - f2;
    } else if (f1 == 0 && f2 == 0) {
      return 0;
    }

    if (f1 != f2) {
      return f1 - f2;
    }
  }
S
Shengliang Guan 已提交
94

wafwerar's avatar
wafwerar 已提交
95 96 97 98
  return 0;

#if 0
  int32_t ucs4_max_len = bytes + 4;
wafwerar's avatar
wafwerar 已提交
99 100
  char *f1_mbs = taosMemoryCalloc(bytes, 1);
  char *f2_mbs = taosMemoryCalloc(bytes, 1);
wafwerar's avatar
wafwerar 已提交
101 102 103 104 105 106 107
  if (taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs) < 0) {
    return -1;
  }
  if (taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs) < 0) {
    return -1;
  }
  int32_t ret = strcmp(f1_mbs, f2_mbs);
wafwerar's avatar
wafwerar 已提交
108 109
  taosMemoryFree(f1_mbs);
  taosMemoryFree(f2_mbs);
wafwerar's avatar
wafwerar 已提交
110 111 112 113
  return ret;
#endif
}

dengyihao's avatar
dengyihao 已提交
114 115 116
TdUcs4 *tasoUcs4Copy(TdUcs4 *target_ucs4, TdUcs4 *source_ucs4, int32_t len_ucs4) {
  assert(taosMemorySize(target_ucs4) >= len_ucs4 * sizeof(TdUcs4));
  return memcpy(target_ucs4, source_ucs4, len_ucs4 * sizeof(TdUcs4));
wafwerar's avatar
wafwerar 已提交
117 118
}

wafwerar's avatar
wafwerar 已提交
119 120
int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs) {
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
121
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile TDengine.\n");
wafwerar's avatar
wafwerar 已提交
122 123
  return -1;
#else
S
Shengliang Guan 已提交
124 125 126 127 128 129 130 131 132 133
  iconv_t cd = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC);
  size_t  ucs4_input_len = ucs4_max_len;
  size_t  outLen = ucs4_max_len;
  if (iconv(cd, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
    iconv_close(cd);
    return -1;
  }

  iconv_close(cd);
  return (int32_t)(ucs4_max_len - outLen);
wafwerar's avatar
wafwerar 已提交
134
#endif
S
Shengliang Guan 已提交
135 136
}

D
dapan1121 已提交
137 138 139 140 141 142 143 144 145
typedef struct {
  iconv_t conv;
  int8_t  inUse;
} SConv;

SConv *gConv = NULL;
int32_t convUsed = 0;
int32_t gConvMaxNum = 0;

146 147
void taosConvInitImpl(void) {
  gConvMaxNum = 512;
D
dapan1121 已提交
148 149 150 151
  gConv = taosMemoryCalloc(gConvMaxNum, sizeof(SConv));
  for (int32_t i = 0; i < gConvMaxNum; ++i) {
    gConv[i].conv = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset);
  }
152
}
D
dapan1121 已提交
153

154 155 156
static TdThreadOnce convInit = PTHREAD_ONCE_INIT;
void taosConvInit() {
  taosThreadOnce(&convInit, taosConvInitImpl);
D
dapan1121 已提交
157 158 159 160 161 162 163 164 165 166
}

void taosConvDestroy() {
  for (int32_t i = 0; i < gConvMaxNum; ++i) {
    iconv_close(gConv[i].conv);
  }
  taosMemoryFreeClear(gConv);
}

void taosAcquireConv(int32_t *idx) {
D
dapan1121 已提交
167
  if (0 == gConvMaxNum) {
168
    taosConvInit();
D
dapan1121 已提交
169 170
  }
  
D
dapan1121 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
  while (true) {
    int32_t used = atomic_add_fetch_32(&convUsed, 1);
    if (used > gConvMaxNum) {
      used = atomic_sub_fetch_32(&convUsed, 1);
      sched_yield();
      continue;
    }
    
    break;
  }

  int32_t startId = taosGetSelfPthreadId() % gConvMaxNum;
  while (true) {
    if (gConv[startId].inUse) {
      startId = (startId + 1) % gConvMaxNum;
      continue;
    }

    int8_t old = atomic_val_compare_exchange_8(&gConv[startId].inUse, 0, 1);
    if (0 == old) {
      break;
    }
  }

  *idx = startId;
}

void taosReleaseConv(int32_t idx) {
D
dapan1121 已提交
199 200 201 202 203 204
  if (0 == gConvMaxNum) {
    iconv_close(gConv[0].conv);
    taosMemoryFreeClear(gConv);
    return;
  }

D
dapan1121 已提交
205
  atomic_store_8(&gConv[idx].inUse, 0);
D
dapan1121 已提交
206
  atomic_sub_fetch_32(&convUsed, 1);
D
dapan1121 已提交
207 208
}

dengyihao's avatar
dengyihao 已提交
209
bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len) {
wafwerar's avatar
wafwerar 已提交
210
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
211
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile TDengine.\n");
wafwerar's avatar
wafwerar 已提交
212 213
  return -1;
#else
S
Shengliang Guan 已提交
214
  memset(ucs4, 0, ucs4_max_len);
D
dapan1121 已提交
215 216 217

  int32_t idx = 0;
  taosAcquireConv(&idx);
S
Shengliang Guan 已提交
218 219
  size_t  ucs4_input_len = mbsLength;
  size_t  outLeft = ucs4_max_len;
D
dapan1121 已提交
220 221
  if (iconv(gConv[idx].conv, (char **)&mbs, &ucs4_input_len, (char **)&ucs4, &outLeft) == -1) {
    taosReleaseConv(idx);
S
Shengliang Guan 已提交
222 223 224
    return false;
  }

D
dapan1121 已提交
225
  taosReleaseConv(idx);
S
Shengliang Guan 已提交
226 227 228 229 230 231 232 233
  if (len != NULL) {
    *len = (int32_t)(ucs4_max_len - outLeft);
    if (*len < 0) {
      return false;
    }
  }

  return true;
wafwerar's avatar
wafwerar 已提交
234
#endif
S
Shengliang Guan 已提交
235 236 237
}

bool taosValidateEncodec(const char *encodec) {
wafwerar's avatar
wafwerar 已提交
238
#ifdef DISALLOW_NCHAR_WITHOUT_ICONV
239 240
  printf("Nchar cannot be read and written without iconv, please install iconv library and recompile TDengine.\n");
  return true;
wafwerar's avatar
wafwerar 已提交
241
#else
S
Shengliang Guan 已提交
242 243 244 245 246 247 248 249 250 251
  iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC);
  if (cd == (iconv_t)(-1)) {
    return false;
  }

  iconv_close(cd);
  return true;
#endif
}

wafwerar's avatar
wafwerar 已提交
252 253
int32_t taosUcs4len(TdUcs4 *ucs4) {
  TdUcs4 *wstr = (TdUcs4 *)ucs4;
S
Shengliang Guan 已提交
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
  if (NULL == wstr) {
    return 0;
  }

  int32_t n = 0;
  while (1) {
    if (0 == *wstr++) {
      break;
    }
    n++;
  }

  return n;
}

dengyihao's avatar
dengyihao 已提交
269
// dst buffer size should be at least 2*len + 1
wafwerar's avatar
wafwerar 已提交
270
int32_t taosHexEncode(const unsigned char *src, char *dst, int32_t len) {
271 272 273 274 275
  if (!dst) {
    return -1;
  }

  for (int32_t i = 0; i < len; ++i) {
wmmhello's avatar
wmmhello 已提交
276
    sprintf(dst + i * 2, "%02x", src[i]);
277 278 279 280 281 282 283 284 285 286
  }

  return 0;
}

int32_t taosHexDecode(const char *src, char *dst, int32_t len) {
  if (!dst) {
    return -1;
  }

wmmhello's avatar
wmmhello 已提交
287
  uint8_t hn, ln, out;
dengyihao's avatar
dengyihao 已提交
288
  for (int i = 0, j = 0; i < len * 2; i += 2, ++j) {
wmmhello's avatar
wmmhello 已提交
289 290
    hn = src[i] > '9' ? src[i] - 'a' + 10 : src[i] - '0';
    ln = src[i + 1] > '9' ? src[i + 1] - 'a' + 10 : src[i + 1] - '0';
291 292 293 294 295 296 297 298

    out = (hn << 4) | ln;
    memcpy(dst + j, &out, 1);
  }

  return 0;
}

wafwerar's avatar
wafwerar 已提交
299 300 301 302 303 304 305 306 307 308 309
int32_t taosWcharWidth(TdWchar wchar) { return wcwidth(wchar); }

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

int32_t taosMbToWchar(TdWchar *pWchar, const char *pStr, int32_t size) { return mbtowc(pWchar, pStr, size); }

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

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

int32_t taosWcharsToMbs(char *pStrs, TdWchar *pWchars, int32_t size) { return wcstombs(pStrs, pWchars, size); }
wafwerar's avatar
wafwerar 已提交
310 311

char *taosStrCaseStr(const char *str, const char *pattern) {
dengyihao's avatar
dengyihao 已提交
312 313 314 315 316 317 318 319 320 321 322 323 324
  size_t i;

  if (!*pattern) return (char *)str;

  for (; *str; str++) {
    if (toupper(*str) == toupper(*pattern)) {
      for (i = 1;; i++) {
        if (!pattern[i]) return (char *)str;
        if (toupper(str[i]) != toupper(pattern[i])) break;
      }
    }
  }
  return NULL;
wafwerar's avatar
wafwerar 已提交
325 326
}

dengyihao's avatar
dengyihao 已提交
327
int64_t taosStr2Int64(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
328
  int64_t tmp = strtoll(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
329
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
330 331
  assert(errno != ERANGE);
  assert(errno != EINVAL);
wafwerar's avatar
wafwerar 已提交
332
#endif
wafwerar's avatar
wafwerar 已提交
333 334 335
  return tmp;
}

dengyihao's avatar
dengyihao 已提交
336
uint64_t taosStr2UInt64(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
337
  uint64_t tmp = strtoull(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
338
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
339 340
  assert(errno != ERANGE);
  assert(errno != EINVAL);
wafwerar's avatar
wafwerar 已提交
341
#endif
wafwerar's avatar
wafwerar 已提交
342 343 344
  return tmp;
}

dengyihao's avatar
dengyihao 已提交
345
int32_t taosStr2Int32(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
346
  int32_t tmp = strtol(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
347
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
348 349
  assert(errno != ERANGE);
  assert(errno != EINVAL);
wafwerar's avatar
wafwerar 已提交
350
#endif
wafwerar's avatar
wafwerar 已提交
351 352 353
  return tmp;
}

dengyihao's avatar
dengyihao 已提交
354
uint32_t taosStr2UInt32(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
355
  uint32_t tmp = strtol(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
356
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
357 358
  assert(errno != ERANGE);
  assert(errno != EINVAL);
wafwerar's avatar
wafwerar 已提交
359
#endif
wafwerar's avatar
wafwerar 已提交
360 361 362
  return tmp;
}

dengyihao's avatar
dengyihao 已提交
363
int16_t taosStr2Int16(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
364
  int32_t tmp = strtol(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
365
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
366 367 368 369
  assert(errno != ERANGE);
  assert(errno != EINVAL);
  assert(tmp >= SHRT_MIN);
  assert(tmp <= SHRT_MAX);
wafwerar's avatar
wafwerar 已提交
370
#endif
wafwerar's avatar
wafwerar 已提交
371 372 373
  return (int16_t)tmp;
}

dengyihao's avatar
dengyihao 已提交
374
uint16_t taosStr2UInt16(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
375
  uint32_t tmp = strtoul(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
376
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
377 378 379
  assert(errno != ERANGE);
  assert(errno != EINVAL);
  assert(tmp <= USHRT_MAX);
wafwerar's avatar
wafwerar 已提交
380
#endif
wafwerar's avatar
wafwerar 已提交
381 382 383
  return (uint16_t)tmp;
}

dengyihao's avatar
dengyihao 已提交
384
int8_t taosStr2Int8(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
385
  int32_t tmp = strtol(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
386
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
387 388 389 390
  assert(errno != ERANGE);
  assert(errno != EINVAL);
  assert(tmp >= SCHAR_MIN);
  assert(tmp <= SCHAR_MAX);
wafwerar's avatar
wafwerar 已提交
391
#endif
wafwerar's avatar
wafwerar 已提交
392 393 394
  return tmp;
}

dengyihao's avatar
dengyihao 已提交
395
uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix) {
wafwerar's avatar
wafwerar 已提交
396
  uint32_t tmp = strtoul(str, pEnd, radix);
wafwerar's avatar
wafwerar 已提交
397
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
398 399 400
  assert(errno != ERANGE);
  assert(errno != EINVAL);
  assert(tmp <= UCHAR_MAX);
wafwerar's avatar
wafwerar 已提交
401
#endif
wafwerar's avatar
wafwerar 已提交
402 403 404
  return tmp;
}

dengyihao's avatar
dengyihao 已提交
405
double taosStr2Double(const char *str, char **pEnd) {
wafwerar's avatar
wafwerar 已提交
406
  double tmp = strtod(str, pEnd);
wafwerar's avatar
wafwerar 已提交
407
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
408 409 410
  assert(errno != ERANGE);
  assert(errno != EINVAL);
  assert(tmp != HUGE_VAL);
wafwerar's avatar
wafwerar 已提交
411
#endif
wafwerar's avatar
wafwerar 已提交
412 413 414
  return tmp;
}

dengyihao's avatar
dengyihao 已提交
415
float taosStr2Float(const char *str, char **pEnd) {
wafwerar's avatar
wafwerar 已提交
416
  float tmp = strtof(str, pEnd);
wafwerar's avatar
wafwerar 已提交
417
#ifdef TD_CHECK_STR_TO_INT_ERROR
wafwerar's avatar
wafwerar 已提交
418 419 420 421
  assert(errno != ERANGE);
  assert(errno != EINVAL);
  assert(tmp != HUGE_VALF);
  assert(tmp != NAN);
wafwerar's avatar
wafwerar 已提交
422
#endif
wafwerar's avatar
wafwerar 已提交
423
  return tmp;
dengyihao's avatar
dengyihao 已提交
424
}