/* * Copyright (c) 2019 TAOS Data, Inc. * * 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 . */ #define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE #include "os.h" // #include "tdef.h" // #include // #include #ifndef DISALLOW_NCHAR_WITHOUT_ICONV #include "iconv.h" #endif int64_t taosStr2int64(const char *str) { char *endptr = NULL; return strtoll(str, &endptr, 10); } bool taosCheckNcharValid(void) { #ifdef DISALLOW_NCHAR_WITHOUT_ICONV return false; #else return true; #endif } 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; } } return 0; #if 0 int32_t ucs4_max_len = bytes + 4; char *f1_mbs = calloc(bytes, 1); char *f2_mbs = calloc(bytes, 1); 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); free(f1_mbs); free(f2_mbs); return ret; #endif } int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs) { #ifdef DISALLOW_NCHAR_WITHOUT_ICONV return -1; #else 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); #endif } bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len) { #ifdef DISALLOW_NCHAR_WITHOUT_ICONV return -1; #else memset(ucs4, 0, ucs4_max_len); iconv_t cd = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset); size_t ucs4_input_len = mbsLength; size_t outLeft = ucs4_max_len; if (iconv(cd, (char**)&mbs, &ucs4_input_len, (char**)&ucs4, &outLeft) == -1) { iconv_close(cd); return false; } iconv_close(cd); if (len != NULL) { *len = (int32_t)(ucs4_max_len - outLeft); if (*len < 0) { return false; } } return true; #endif } bool taosValidateEncodec(const char *encodec) { #ifdef DISALLOW_NCHAR_WITHOUT_ICONV return false; #else iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC); if (cd == (iconv_t)(-1)) { return false; } iconv_close(cd); return true; #endif } int32_t taosUcs4len(TdUcs4 *ucs4) { TdUcs4 *wstr = (TdUcs4 *)ucs4; if (NULL == wstr) { return 0; } int32_t n = 0; while (1) { if (0 == *wstr++) { break; } n++; } return n; } // #ifdef USE_LIBICONV // #include "iconv.h" // int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) { // 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); // } // bool taosMbsToUcs4(char *mbs, size_t mbsLength, char *ucs4, int32_t ucs4_max_len, int32_t *len) { // memset(ucs4, 0, ucs4_max_len); // iconv_t cd = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset); // size_t ucs4_input_len = mbsLength; // size_t outLeft = ucs4_max_len; // if (iconv(cd, &mbs, &ucs4_input_len, &ucs4, &outLeft) == -1) { // iconv_close(cd); // return false; // } // iconv_close(cd); // if (len != NULL) { // *len = (int32_t)(ucs4_max_len - outLeft); // if (*len < 0) { // return false; // } // } // return true; // } // bool taosValidateEncodec(const char *encodec) { // iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC); // if (cd == (iconv_t)(-1)) { // return false; // } // iconv_close(cd); // return true; // } // #else // int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) { // mbstate_t state = {0}; // int32_t len = (int32_t)wcsnrtombs(NULL, (const wchar_t **)&ucs4, ucs4_max_len / 4, 0, &state); // if (len < 0) { // return -1; // } // memset(&state, 0, sizeof(state)); // len = wcsnrtombs(mbs, (const wchar_t **)&ucs4, ucs4_max_len / 4, (size_t)len, &state); // if (len < 0) { // return -1; // } // return len; // } // bool taosMbsToUcs4(const char *mbs, size_t mbsLength, char *ucs4, int32_t ucs4_max_len, int32_t *len) { // memset(ucs4, 0, ucs4_max_len); // mbstate_t state = {0}; // int32_t retlen = mbsnrtowcs((wchar_t *)ucs4, (const char **)&mbs, mbsLength, ucs4_max_len / 4, &state); // *len = retlen; // return retlen >= 0; // } // bool taosValidateEncodec(const char *encodec) { // return true; // } // #endif // #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) // /* // * windows implementation // */ // #ifdef HAVE_CONFIG_H // #include // #endif // #include // #include // #include // #include // #include // #if STDC_HEADERS // #include // #else // char *malloc(), *realloc(); // #endif // /* Always add at least this many bytes when extending the buffer. */ // #define MIN_CHUNK 64 // /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR // + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from // malloc (or NULL), pointing to *N characters of space. It is realloc'd // as necessary. Return the number of characters read (not including the // null terminator), or -1 on error or EOF. On a -1 return, the caller // should check feof(), if not then errno has been set to indicate // the error. */ // int32_t getstr(char **lineptr, size_t *n, FILE *stream, char terminator, int32_t offset) { // int32_t nchars_avail; /* Allocated but unused chars in *LINEPTR. */ // char * read_pos; /* Where we're reading into *LINEPTR. */ // int32_t ret; // if (!lineptr || !n || !stream) { // errno = EINVAL; // return -1; // } // if (!*lineptr) { // *n = MIN_CHUNK; // *lineptr = malloc(*n); // if (!*lineptr) { // errno = ENOMEM; // return -1; // } // } // nchars_avail = (int32_t)(*n - offset); // read_pos = *lineptr + offset; // for (;;) { // int32_t save_errno; // register int32_t c = getc(stream); // save_errno = errno; // /* We always want at least one char left in the buffer, since we // always (unless we get an error while reading the first char) // NUL-terminate the line buffer. */ // assert((*lineptr + *n) == (read_pos + nchars_avail)); // if (nchars_avail < 2) { // if (*n > MIN_CHUNK) // *n *= 2; // else // *n += MIN_CHUNK; // nchars_avail = (int32_t)(*n + *lineptr - read_pos); // char* lineptr1 = realloc(*lineptr, *n); // if (!lineptr1) { // errno = ENOMEM; // return -1; // } // *lineptr = lineptr1; // read_pos = *n - nchars_avail + *lineptr; // assert((*lineptr + *n) == (read_pos + nchars_avail)); // } // if (ferror(stream)) { // /* Might like to return partial line, but there is no // place for us to store errno. And we don't want to just // lose errno. */ // errno = save_errno; // return -1; // } // if (c == EOF) { // /* Return partial line, if any. */ // if (read_pos == *lineptr) // return -1; // else // break; // } // *read_pos++ = c; // nchars_avail--; // if (c == terminator) /* Return the line. */ // break; // } // /* Done - NUL terminate and return the number of chars read. */ // *read_pos = '\0'; // ret = (int32_t)(read_pos - (*lineptr + offset)); // return ret; // } // int32_t tgetline(char **lineptr, size_t *n, FILE *stream) { return getstr(lineptr, n, stream, '\n', 0); } // /* // * Get next token from string *stringp, where tokens are possibly-empty // * strings separated by characters from delim. // * // * Writes NULs into the string at *stringp to end tokens. // * delim need not remain constant from call to call. // * On return, *stringp points past the last NUL written (if there might // * be further tokens), or is NULL (if there are definitely no moretokens). // * // * If *stringp is NULL, strsep returns NULL. // */ // char *strsep(char **stringp, const char *delim) { // char * s; // const char *spanp; // int32_t c, sc; // char *tok; // if ((s = *stringp) == NULL) // return (NULL); // 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 */ // } // char *getpass(const char *prefix) { // static char passwd[TSDB_PASSWORD_LEN] = {0}; // memset(passwd, 0, TSDB_PASSWORD_LEN); // //printf("%s", prefix); // int32_t index = 0; // char ch; // while (index < TSDB_PASSWORD_LEN) { // ch = getch(); // if (ch == '\n' || ch == '\r') { // break; // } else { // passwd[index++] = ch; // } // } // return passwd; // } // int32_t twcslen(const wchar_t *wcs) { // int32_t *wstr = (int32_t *)wcs; // if (NULL == wstr) { // return 0; // } // int32_t n = 0; // while (1) { // if (0 == *wstr++) { // break; // } // n++; // } // return n; // } // int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes) { // for (int32_t i = 0; i < bytes; i += TSDB_NCHAR_SIZE) { // 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; // } // } // return 0; // #if 0 // int32_t ucs4_max_len = bytes + 4; // char *f1_mbs = calloc(bytes, 1); // char *f2_mbs = calloc(bytes, 1); // 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); // free(f1_mbs); // free(f2_mbs); // return ret; // #endif // } // /* Copy memory to memory until the specified number of bytes // has been copied, return pointer to following byte. // Overlap is NOT handled correctly. */ // void *mempcpy(void *dest, const void *src, size_t len) { // return (char*)memcpy(dest, src, len) + len; // } // /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ // char *stpcpy (char *dest, const char *src) { // size_t len = strlen (src); // return (char*)memcpy(dest, src, len + 1) + len; // } // /* 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. */ // char *stpncpy (char *dest, const char *src, size_t n) { // size_t size = strnlen (src, n); // memcpy (dest, src, size); // dest += size; // if (size == n) // return dest; // return memset (dest, '\0', n - size); // } // #else // /* // * linux and darwin implementation // */ // int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes, int8_t ncharSize) { // return wcsncmp((wchar_t *)f1_ucs4, (wchar_t *)f2_ucs4, bytes / ncharSize); // } // #endif