static tb_size_t tb_strlcpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n) { // check tb_assert_and_check_return_val(s1 && s2, 0); // no size or same? tb_check_return_val(n && s1 != s2, tb_strlen(s1)); // copy #if 0 tb_char_t const* s = s2; --n; while (*s1 = *s2) { if (n) { --n; ++s1; } ++s2; } return s2 - s; #else tb_size_t sn = tb_strlen(s2); tb_memcpy(s1, s2, tb_min(sn + 1, n)); return tb_min(sn, n); #endif }
tb_char_t const* tb_regex_replace_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength) { // check tb_assert_and_check_return_val(cstr && replace_cstr, tb_null); // done return tb_regex_replace(regex, cstr, tb_strlen(cstr), start, replace_cstr, tb_strlen(replace_cstr), plength); }
tb_char_t const* tb_regex_replace_simple(tb_regex_ref_t regex, tb_char_t const* cstr, tb_char_t const* replace_cstr) { // check tb_assert_and_check_return_val(cstr && replace_cstr, tb_null); // done return tb_regex_replace(regex, cstr, tb_strlen(cstr), 0, replace_cstr, tb_strlen(replace_cstr), tb_null); }
/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_long_t tb_strcmp(tb_char_t const* s1, tb_char_t const* s2) { // check #ifdef __tb_debug__ { // check overflow? tb_strlen(s1); tb_strlen(s2); } #endif // done return tb_strcmp_impl(s1, s2); }
tb_bool_t tb_directory_copy(tb_char_t const* path, tb_char_t const* dest) { // the absolute path tb_char_t full0[TB_PATH_MAXN]; path = tb_path_absolute(path, full0, TB_PATH_MAXN); tb_assert_and_check_return_val(path, tb_false); // the dest path tb_char_t full1[TB_PATH_MAXN]; dest = tb_path_absolute(dest, full1, TB_PATH_MAXN); tb_assert_and_check_return_val(dest, tb_false); // walk copy tb_value_t tuple[3]; tuple[0].cstr = dest; tuple[1].ul = tb_strlen(path); tuple[2].b = tb_true; tb_directory_walk(path, -1, tb_true, tb_directory_walk_copy, tuple); // ok? tb_bool_t ok = tuple[2].b; // copy empty directory? if (ok && !tb_file_info(dest, tb_null)) return tb_directory_create(dest); // ok? return ok; }
static tb_char_t* tb_strcpy_impl(tb_char_t* s1, tb_char_t const* s2) { tb_assert_and_check_return_val(s1 && s2, tb_null); __tb_register__ tb_char_t* s = s1; if (s1 == s2) return s; #if 1 tb_memcpy(s1, s2, tb_strlen(s2) + 1); #elif defined(__tb_small__) while ((*s++ = *s2++)) ; #else while (1) { if (!(s1[0] = s2[0])) break; if (!(s1[1] = s2[1])) break; if (!(s1[2] = s2[2])) break; if (!(s1[3] = s2[3])) break; s1 += 4; s2 += 4; } #endif return s; }
/* *@note * * fputs(string, stdout) exists compatibility issue when vs2008 => vs2015 * * error: ___iob_func undefined in vs2015 */ tb_void_t tb_print(tb_char_t const* string) { // check tb_check_return(string); // get stdout HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); tb_assert_and_check_return(handle != INVALID_HANDLE_VALUE); // the data and size tb_byte_t const* data = (tb_byte_t const*)string; tb_size_t size = tb_strlen(string) + 1; // write string to stdout tb_size_t writ = 0; while (writ < size) { // write to the stdout DWORD real = 0; if (!WriteFile(handle, data + writ, (DWORD)(size - writ), &real, tb_null)) break; // update writted size writ += (tb_size_t)real; } }
static tb_char_t* tb_strncpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n) { // check tb_assert_and_check_return_val(s1 && s2, s1); // no size or same? tb_check_return_val(n && s1 != s2, s1); // copy #if 0 tb_char_t* s = s1; while (n) { if (*s = *s2) s2++; ++s; --n; } return s1; #else tb_size_t sn = tb_strlen(s2); tb_size_t cn = tb_min(sn, n); tb_size_t fn = sn < n? n - sn : 0; tb_memcpy(s1, s2, cn); if (fn) tb_memset(s1 + cn, 0, fn); return s1; #endif }
static tb_bool_t xm_semver_select_from_branches(lua_State* lua, tb_int_t fromidx, tb_char_t const* range_str, tb_size_t range_len) { lua_Integer i = 0; luaL_checktype(lua, fromidx, LUA_TTABLE); for (i = lua_objlen(lua, fromidx); i > 0; --i) { lua_pushinteger(lua, i); lua_gettable(lua, fromidx); tb_char_t const* source_str = luaL_checkstring(lua, -1); tb_check_continue(source_str); tb_size_t source_len = tb_strlen(source_str); if (source_len == range_len && tb_memcmp(source_str, range_str, source_len) == 0) { lua_createtable(lua, 0, 2); lua_pushlstring(lua, source_str, source_len); lua_setfield(lua, -2, "version"); lua_pushstring(lua, "branches"); lua_setfield(lua, -2, "source"); // ok return tb_true; } } // no matches return tb_false; }
tb_size_t tb_murmur_make_from_cstr(tb_char_t const* cstr, tb_size_t seed) { // check tb_assert_and_check_return_val(cstr, 0); // make it return tb_murmur_make((tb_byte_t const*)cstr, tb_strlen(cstr), seed); }
tb_uint64_t tb_fnv64_1a_make_from_cstr(tb_char_t const* cstr, tb_uint64_t seed) { // check tb_assert_and_check_return_val(cstr, 0); // make it return tb_fnv64_1a_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed); }
tb_long_t tb_regex_match_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults) { // check tb_assert_and_check_return_val(cstr, -1); // done return tb_regex_match(regex, cstr, tb_strlen(cstr), start, plength, presults); }
tb_char_t const* tb_regex_replace_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_char_t const* replace_cstr) { // check tb_assert_and_check_return_val(cstr && replace_cstr, tb_null); // done return tb_regex_replace_done(pattern, mode, cstr, tb_strlen(cstr), 0, replace_cstr, tb_strlen(replace_cstr), tb_null); }
tb_long_t tb_charset_conv_cstr(tb_size_t ftype, tb_size_t ttype, tb_char_t const* cstr, tb_byte_t* data, tb_size_t size) { // check tb_assert_and_check_return_val(TB_CHARSET_TYPE_OK(ftype) && TB_CHARSET_TYPE_OK(ttype) && cstr && data && size, -1); // conv return tb_charset_conv_data(ftype, ttype, (tb_byte_t const*)cstr, tb_strlen(cstr), data, size); }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_utils_url_main(tb_int_t argc, tb_char_t** argv) { tb_char_t ob[4096]; tb_size_t on = tb_url_encode(argv[1], tb_strlen(argv[1]), ob, 4096); //tb_size_t on = tb_url_decode(argv[1], tb_strlen(argv[1]), ob, 4096); tb_trace_i("%s: %lu", ob, on); return 0; }
tb_vector_ref_t tb_regex_match_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr) { // check tb_assert_and_check_return_val(cstr, tb_null); // done tb_vector_ref_t results = tb_null; return tb_regex_match_done(pattern, mode, cstr, tb_strlen(cstr), 0, tb_null, &results) >= 0? results : tb_null; }
static tb_bool_t tb_directory_walk_impl(tb_char_t const* path, tb_bool_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(path && func, tb_false); // last tb_long_t last = tb_strlen(path) - 1; tb_assert_and_check_return_val(last >= 0, tb_false); // done tb_bool_t ok = tb_true; tb_char_t temp[4096] = {0}; DIR* directory = tb_null; if ((directory = opendir(path))) { // walk struct dirent* item = tb_null; while ((item = readdir(directory))) { // check tb_assert_and_check_continue(item->d_reclen); // the item name tb_char_t name[1024] = {0}; tb_strncpy(name, item->d_name, tb_min(item->d_reclen, sizeof(name) - 1)); if (tb_strcmp(name, ".") && tb_strcmp(name, "..")) { // the temp path tb_long_t n = tb_snprintf(temp, 4095, "%s%s%s", path, path[last] == '/'? "" : "/", name); if (n >= 0) temp[n] = '\0'; // the file info tb_file_info_t info = {0}; if (tb_file_info(temp, &info)) { // do callback if (prefix) ok = func(temp, &info, priv); tb_check_break(ok); // walk to the next directory if (info.type == TB_FILE_TYPE_DIRECTORY && recursion) ok = tb_directory_walk_impl(temp, recursion, prefix, func, priv); tb_check_break(ok); // do callback if (!prefix) ok = func(temp, &info, priv); tb_check_break(ok); } } } // exit directory closedir(directory); } // continue ? return ok; }
tb_vector_ref_t tb_regex_match_simple(tb_regex_ref_t regex, tb_char_t const* cstr) { // check tb_assert_and_check_return_val(cstr, tb_null); // done tb_vector_ref_t results = tb_null; return tb_regex_match(regex, cstr, tb_strlen(cstr), 0, tb_null, &results) >= 0? results : tb_null; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_utils_fnv32_main(tb_int_t argc, tb_char_t** argv) { // data tb_byte_t const* data = (tb_byte_t const*)argv[1]; tb_size_t size = tb_strlen((tb_char_t const*)data); // trace tb_trace_i("[fnv32]: %x", tb_fnv32_encode(data, size)); return 0; }
tb_long_t tb_puts(tb_char_t const* string) { // check tb_check_return_val(string, 0); // print it tb_printl(string); // ok? return tb_strlen(string); }
static tb_int_t tb_ssl_bio_method_puts(BIO* bio, tb_char_t const* data) { // check tb_assert_and_check_return_val(bio && data, -1); // trace tb_trace_d("bio: puts: %s", data); // writ return tb_ssl_bio_method_writ(bio, data, tb_strlen(data)); }
tb_size_t tb_directory_current(tb_char_t* path, tb_size_t maxn) { // check tb_assert_and_check_return_val(path && maxn, 0); // the current directory tb_size_t size = 0; if (getcwd(path, maxn - 1)) size = tb_strlen(path); // ok? return size; }
static tb_void_t tb_test_strlen(tb_char_t const* s) { __tb_volatile__ tb_long_t n = 1000000; __tb_volatile__ tb_long_t r = 0; tb_hong_t t = tb_mclock(); while (n--) { r = tb_strlen(s); } t = tb_mclock() - t; tb_printf("%lld ms, tb_test_strlen(%s) = %ld\n", t, s, r); }
// semver.compare("v1.0.1-beta", "1.2") > 0? tb_int_t xm_semver_compare(lua_State* lua) { // check tb_assert_and_check_return_val(lua, 0); // get the version1 string tb_char_t const* version1_str = luaL_checkstring(lua, 1); tb_check_return_val(version1_str, 0); // get the version2 string tb_char_t const* version2_str = luaL_checkstring(lua, 2); tb_check_return_val(version2_str, 0); // try to parse version1 string semver_t semver1 = {0}; if (semver_tryn(&semver1, version1_str, tb_strlen(version1_str))) { lua_pushnil(lua); lua_pushfstring(lua, "unable to parse semver '%s'", version1_str); return 2; } // try to parse version2 string semver_t semver2 = {0}; if (semver_tryn(&semver2, version2_str, tb_strlen(version2_str))) { lua_pushnil(lua); lua_pushfstring(lua, "unable to parse semver '%s'", version2_str); return 2; } // do compare lua_pushinteger(lua, semver_pcmp(&semver1, &semver2)); // end semver_dtor(&semver1); semver_dtor(&semver2); return 1; }
static tb_void_t tb_element_str_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data) { // check tb_assert_and_check_return(element && element->dupl && buff); #if 0 // free it if (element->free) element->free(element, buff); // dupl it element->dupl(element, buff, data); #else // replace it tb_pointer_t cstr = *((tb_pointer_t*)buff); if (cstr && data) { // attempt to replace it tb_char_t* p = (tb_char_t*)cstr; tb_char_t const* q = (tb_char_t const*)data; while (*p && *q) *p++ = *q++; // not enough space? if (!*p && *q) { // the left size tb_size_t left = tb_strlen(q); tb_assert_abort(left); // the copy size tb_size_t copy = p - (tb_char_t*)cstr; // grow size cstr = tb_ralloc(cstr, copy + left + 1); tb_assert_abort(cstr); // copy the left data tb_strlcpy((tb_char_t*)cstr + copy, q, left + 1); // update the cstr *((tb_pointer_t*)buff) = cstr; } // end else *p = '\0'; } // duplicate it else if (data) element->dupl(element, buff, data); // free it else if (element->free) element->free(element, buff); // clear it else *((tb_char_t const**)buff) = tb_null; #endif }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_utils_md5_main(tb_int_t argc, tb_char_t** argv) { tb_byte_t ob[16]; tb_size_t on = tb_md5_encode((tb_byte_t const*)argv[1], tb_strlen(argv[1]), ob, 16); if (on != 16) return 0; tb_size_t i = 0; tb_char_t md5[256] = {0}; for (i = 0; i < 16; ++i) tb_snprintf(md5 + (i << 1), 3, "%02X", ob[i]); tb_printf("%s: %lu\n", md5, on); return 0; }
static tb_bool_t tb_environment_set_impl(tb_char_t const* name, tb_char_t const* value) { // check tb_assert_and_check_return_val(name, tb_false); // done tb_bool_t ok = tb_false; tb_size_t size = 0; tb_wchar_t* value_w = tb_null; tb_size_t value_n = 0; do { // make name tb_wchar_t name_w[512] = {0}; tb_size_t name_n = tb_atow(name_w, name, tb_arrayn(name_w)); tb_assert_and_check_break(name_n); // exists value? if (value) { // make value value_n = tb_strlen(value); value_w = (tb_wchar_t*)tb_malloc0(sizeof(tb_wchar_t) * (value_n + 1)); tb_assert_and_check_break(value_w); // init value if (!tb_atow(value_w, value, value_n + 1)) break; // set it if (!tb_kernel32()->SetEnvironmentVariableW(name_w, value_w)) break; } // remove this variable else { // remove it if (!tb_kernel32()->SetEnvironmentVariableW(name_w, tb_null)) break; } // ok ok = tb_true; } while (0); // exit data if (value_w) tb_free(value_w); value_w = tb_null; // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_utils_crc_main(tb_int_t argc, tb_char_t** argv) { tb_byte_t* p = (tb_byte_t*)argv[1]; tb_size_t n = tb_strlen((tb_char_t const*)p); #ifndef __tb_small__ tb_printf("[crc]: TB_CRC_MODE_8_ATM = %x\n", tb_crc_encode(TB_CRC_MODE_8_ATM, 0, p, n)); tb_printf("[crc]: TB_CRC_MODE_16_ANSI = %x\n", tb_crc_encode(TB_CRC_MODE_16_ANSI, 0, p, n)); tb_printf("[crc]: TB_CRC_MODE_16_CCITT = %x\n", tb_crc_encode(TB_CRC_MODE_16_CCITT, 0, p, n)); tb_printf("[crc]: TB_CRC_MODE_32_IEEE = %x\n", tb_crc_encode(TB_CRC_MODE_32_IEEE, 0, p, n)); tb_printf("[crc]: TB_CRC_MODE_32_IEEE_LE = %x\n", tb_crc_encode(TB_CRC_MODE_32_IEEE_LE, 0, p, n)); #else tb_printf("[crc]: TB_CRC_MODE_16_CCITT = %x\n", tb_crc_encode(TB_CRC_MODE_16_CCITT, 0, p, n)); tb_printf("[crc]: TB_CRC_MODE_32_IEEE_LE = %x\n", tb_crc_encode(TB_CRC_MODE_32_IEEE_LE, 0, p, n)); #endif return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t xm_semver_select_from_versions_tags(lua_State* lua, tb_int_t fromidx, semver_t* semver, semver_range_t const* range, semvers_t* matches) { // clear matches semvers_pclear(matches); // select all matches lua_Integer i = 0; luaL_checktype(lua, fromidx, LUA_TTABLE); for (i = lua_objlen(lua, fromidx); i > 0; --i) { lua_pushinteger(lua, i); lua_gettable(lua, fromidx); tb_char_t const* source_str = luaL_checkstring(lua, -1); if (source_str && semver_tryn(semver, source_str, tb_strlen(source_str)) == 0) { if (semver_range_pmatch(semver, range)) semvers_ppush(matches, *semver); else semver_dtor(semver); } } // no matches? tb_check_return_val(matches->length, tb_false); // sort matches semvers_psort(matches); // get the newest version semver_t top = semvers_ppop(matches); lua_createtable(lua, 0, 2); // return results lua_pushstring(lua, top.raw); lua_setfield(lua, -2, "version"); lua_pushstring(lua, fromidx == 2? "versions" : "tags"); lua_setfield(lua, -2, "source"); // exit the popped semver semver_dtor(&top); // ok return tb_true; }
tb_char_t* tb_strdup(tb_char_t const* s) { // check tb_assert_and_check_return_val(s, tb_null); // make __tb_register__ tb_size_t n = tb_strlen(s); __tb_register__ tb_char_t* p = tb_malloc_cstr(n + 1); tb_assert_and_check_return_val(p, tb_null); // copy tb_memcpy(p, s, n); // end p[n] = '\0'; // ok return p; }