tb_void_t tb_sha_spak(tb_sha_t* sha, tb_byte_t const* data, tb_size_t size) { // check tb_assert_and_check_return(sha && data); // update count tb_uint32_t j = (tb_uint32_t)sha->count & 63; sha->count += size; // done tb_uint32_t i; #ifdef __tb_small__ for (i = 0; i < size; i++) { sha->buffer[j++] = data[i]; if (64 == j) { sha->transform(sha->state, sha->buffer); j = 0; } } #else if ((j + size) > 63) { tb_memcpy(&sha->buffer[j], data, (i = 64 - j)); sha->transform(sha->state, sha->buffer); for (; i + 63 < size; i += 64) sha->transform(sha->state, &data[i]); j = 0; } else i = 0; tb_memcpy(&sha->buffer[j], &data[i], size - i); #endif }
tb_size_t tb_wcslcpy(tb_wchar_t* s1, tb_wchar_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_wcslen(s1)); // copy #if 0 tb_wchar_t const* s = s2; --n; while (*s1 = *s2) { if (n) { --n; ++s1; } ++s2; } return s2 - s; #else tb_size_t sn = tb_wcslen(s2); tb_memcpy(s1, s2, tb_min(sn + 1, n) * sizeof(tb_wchar_t)); return tb_min(sn, n); #endif }
tb_wchar_t* tb_wcscpy(tb_wchar_t* s1, tb_wchar_t const* s2) { tb_assert_and_check_return_val(s1 && s2, tb_null); __tb_register__ tb_wchar_t* s = s1; if (s1 == s2) return s; #if 1 tb_memcpy(s1, s2, (tb_wcslen(s2) + 1) * sizeof(tb_wchar_t)); #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; }
/*!the insertion sort * * <pre> * old: 5 2 6 2 8 6 1 * * (hole) * step1: ((5)) 2 6 2 8 6 1 * (next) <= * * (hole) * step2: ((2)) (5) 6 2 8 6 1 * (next) <= * * (hole) * step3: 2 5 ((6)) 2 8 6 1 * (next) <= * * (hole) * step4: 2 ((2)) (5) (6) 8 6 1 * (next) <= * * (hole) * step5: 2 2 5 6 ((8)) 6 1 * (next) <= * * (hole) * step6: 2 2 5 6 ((6)) (8) 1 * (next) <= * * (hole) * step7: ((1)) (2) (2) (5) (6) (6) (8) * (next) * </pre> */ tb_void_t tb_insert_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // check tb_assert_and_check_return(iterator); tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD)); tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE)); tb_check_return(head != tail); // init tb_size_t step = tb_iterator_step(iterator); tb_pointer_t temp = step > sizeof(tb_pointer_t)? tb_malloc(step) : tb_null; tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp); // the comparer if (!comp) comp = tb_iterator_comp; // sort tb_size_t last, next; for (next = tb_iterator_next(iterator, head); next != tail; next = tb_iterator_next(iterator, next)) { // save next if (step <= sizeof(tb_pointer_t)) temp = tb_iterator_item(iterator, next); else tb_memcpy(temp, tb_iterator_item(iterator, next), step); // look for hole and move elements[hole, next - 1] => [hole + 1, next] for (last = next; last != head && (last = tb_iterator_prev(iterator, last), comp(iterator, temp, tb_iterator_item(iterator, last)) < 0); next = last) tb_iterator_copy(iterator, next, tb_iterator_item(iterator, last)); // item => hole tb_iterator_copy(iterator, next, temp); } // free if (temp && step > sizeof(tb_pointer_t)) tb_free(temp); }
tb_wchar_t* tb_wcsncpy(tb_wchar_t* s1, tb_wchar_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_wchar_t* s = s1; while (n) { if (*s = *s2) s2++; ++s; --n; } return s1; #else tb_size_t sn = tb_wcslen(s2); tb_size_t cn = tb_min(sn, n); tb_size_t fn = sn < n? n - sn : 0; tb_memcpy(s1, s2, cn * sizeof(tb_wchar_t)); if (fn) tb_memset(s1 + cn, 0, fn * sizeof(tb_wchar_t)); return s1; #endif }
tb_void_t tb_vector_copy(tb_vector_ref_t vector, tb_vector_ref_t hcopy) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)vector; tb_vector_impl_t const* copy = (tb_vector_impl_t const*)hcopy; tb_assert_and_check_return(impl && copy); // check func tb_assert_and_check_return(impl->func.type == copy->func.type); tb_assert_and_check_return(impl->func.size == copy->func.size); // check itor tb_assert_and_check_return(impl->itor.mode == copy->itor.mode); tb_assert_and_check_return(impl->itor.step == copy->itor.step); // null? clear it if (!copy->size) { tb_vector_clear(vector); return ; } // resize if small if (impl->size < copy->size) tb_vector_resize(vector, copy->size); tb_assert_and_check_return(impl->data && copy->data && impl->size >= copy->size); // copy data if (copy->data != impl->data) tb_memcpy(impl->data, copy->data, copy->size * copy->func.size); // copy size impl->size = copy->size; }
int sha256_process(sha256_state * md, const unsigned char *in, unsigned long inlen) { unsigned long n; int err; if (md == NULL || in == NULL) return -1; if (md->curlen > sizeof(md->buf)) return -1; while (inlen > 0) { if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) { if ((err = sha256_compress(md, (unsigned char *)in)) != 0) { return err; } md->length += SHA256_BLOCK_SIZE * 8; in += SHA256_BLOCK_SIZE; inlen -= SHA256_BLOCK_SIZE; } else { n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen)); tb_memcpy(md->buf + md->curlen, in, (size_t)n); md->curlen += n; in += n; inlen -= n; if (md->curlen == SHA256_BLOCK_SIZE) { if ((err = sha256_compress(md, md->buf)) != 0) { return err; } md->length += 8*SHA256_BLOCK_SIZE; md->curlen = 0; } } } return 0; }
tb_long_t tb_queue_buffer_writ(tb_queue_buffer_ref_t buffer, tb_byte_t const* data, tb_size_t size) { // check tb_assert_and_check_return_val(buffer && data && buffer->maxn, -1); // no data? if (!buffer->data) { // make data buffer->data = tb_malloc_bytes(buffer->maxn); tb_assert_and_check_return_val(buffer->data, -1); // init it buffer->head = buffer->data; buffer->size = 0; } tb_assert_and_check_return_val(buffer->data && buffer->head, -1); // full? tb_size_t left = buffer->maxn - buffer->size; tb_check_return_val(left, 0); // attempt to write data in tail directly if the tail space is enough tb_byte_t* tail = buffer->head + buffer->size; if (buffer->data + buffer->maxn >= tail + size) { tb_memcpy(tail, data, size); buffer->size += size; return (tb_long_t)size; } // move data to head if (buffer->head != buffer->data) { if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size); buffer->head = buffer->data; } // write data tb_size_t writ = left > size? size : left; tb_memcpy(buffer->data + buffer->size, data, writ); buffer->size += writ; // ok return writ; }
static tb_void_t tb_iterator_mem_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count); // copy tb_memcpy((tb_byte_t*)((tb_array_iterator_ref_t)iterator)->items + itor * iterator->step, item, iterator->step); }
tb_char_t const* tb_addrinfo_name(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn) { // check tb_assert_and_check_return_val(addr && name && maxn, tb_null); #if defined(TB_CONFIG_POSIX_HAVE_GETNAMEINFO) // load socket address struct sockaddr_storage saddr; socklen_t saddrlen = (socklen_t)tb_sockaddr_load(&saddr, addr); tb_assert_and_check_return_val(saddrlen, tb_null); // get host name from address return !getnameinfo((struct sockaddr const*)&saddr, saddrlen, name, maxn, tb_null, 0, NI_NAMEREQD)? name : tb_null; #elif defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME) // done struct hostent* hostaddr = tb_null; switch (tb_ipaddr_family(addr)) { case TB_IPADDR_FAMILY_IPV4: { // init ip address struct in_addr ipaddr = {0}; ipaddr.s_addr = tb_ipaddr_ip_is_any(addr)? INADDR_ANY : addr->u.ipv4.u32; // get host name from address hostaddr = gethostbyaddr((tb_char_t const*)&ipaddr, sizeof(ipaddr), AF_INET); } break; case TB_IPADDR_FAMILY_IPV6: { // init ip address struct in6_addr ipaddr; tb_memset(&ipaddr, 0, sizeof(ipaddr)); // save ipv6 if (tb_ipaddr_ip_is_any(addr)) ipaddr = in6addr_any; else tb_memcpy(ipaddr.s6_addr, addr->u.ipv6.addr.u8, sizeof(ipaddr.s6_addr)); // get host name from address hostaddr = gethostbyaddr((tb_char_t const*)&ipaddr, sizeof(ipaddr), AF_INET6); } break; default: break; } tb_check_return_val(hostaddr && hostaddr->h_name, tb_null); // save name tb_strlcpy(name, hostaddr->h_name, maxn); // ok? return name; #else tb_trace_noimpl(); return tb_null; #endif }
static tb_void_t tb_iterator_init_mem_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_assert_return(iterator); tb_assert_return(itor < (tb_size_t)iterator->priv && item); // copy tb_memcpy((tb_byte_t*)iterator->data + itor * iterator->step, item, iterator->step); }
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(left); // the copy size tb_size_t copy = p - (tb_char_t*)cstr; // grow size cstr = tb_ralloc(cstr, copy + left + 1); tb_assert(cstr); // copy the left data tb_memcpy((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 }
tb_void_t g2_style_copy(tb_handle_t style, tb_handle_t copy) { g2_style_t* gstyle = (g2_style_t*)style; g2_style_t* gcopy = (g2_style_t*)style; tb_assert_and_check_return(gstyle && gcopy); // refn++ if (gcopy->shader) g2_shader_inc(gcopy->shader); // refn-- if (gstyle->shader) g2_shader_dec(gstyle->shader); // copy tb_memcpy(gstyle, copy, sizeof(g2_style_t)); }
tb_char_t* tb_strndup(tb_char_t const* s, tb_size_t n) { // check tb_assert_and_check_return_val(s, tb_null); // done n = tb_strnlen(s, n); __tb_register__ tb_char_t* p = tb_malloc_cstr(n + 1); if (p) { tb_memcpy(p, s, n); p[n] = '\0'; } return p; }
tb_void_t tb_md5_exit(tb_md5_t* md5, tb_byte_t* data, tb_size_t size) { // check tb_assert_and_check_return(md5 && data); // init tb_uint32_t ip[16]; tb_int_t mdi = 0; tb_size_t i = 0; tb_size_t ii = 0; tb_size_t pad_n = 0; // save number of bits ip[14] = md5->i[0]; ip[15] = md5->i[1]; // compute number of bytes mod 64 mdi = (tb_int_t)((md5->i[0] >> 3) & 0x3F); // pad out to 56 mod 64 pad_n = (mdi < 56) ? (56 - mdi) : (120 - mdi); tb_md5_spak (md5, g_md5_padding, pad_n); // append length ip bits and transform for (i = 0, ii = 0; i < 14; i++, ii += 4) { ip[i] = (((tb_uint32_t)md5->ip[ii + 3]) << 24) | (((tb_uint32_t)md5->ip[ii + 2]) << 16) | (((tb_uint32_t)md5->ip[ii + 1]) << 8) | ((tb_uint32_t)md5->ip[ii]); } tb_md5_transform (md5->sp, ip); // store buffer ip data for (i = 0, ii = 0; i < 4; i++, ii += 4) { md5->data[ii] = (tb_byte_t)( md5->sp[i] & 0xff); md5->data[ii+1] = (tb_byte_t)((md5->sp[i] >> 8) & 0xff); md5->data[ii+2] = (tb_byte_t)((md5->sp[i] >> 16) & 0xff); md5->data[ii+3] = (tb_byte_t)((md5->sp[i] >> 24) & 0xff); } // output tb_memcpy(data, md5->data, 16); }
tb_byte_t* tb_buffer_memncpyp(tb_buffer_t* buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n) { // check tb_assert_and_check_return_val(buffer && b, tb_null); // check tb_check_return_val(n, tb_buffer_data(buffer)); // resize tb_byte_t* d = tb_buffer_resize(buffer, p + n); tb_assert_and_check_return_val(d, tb_null); // copy it tb_memcpy(d + p, b, n); // ok return d; }
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; }
tb_long_t tb_queue_buffer_read(tb_queue_buffer_ref_t buffer, tb_byte_t* data, tb_size_t size) { // check tb_assert_and_check_return_val(buffer && data, -1); // no data? tb_check_return_val(buffer->data && buffer->size && size, 0); tb_assert_and_check_return_val(buffer->head, -1); // read data tb_long_t read = buffer->size > size? size : buffer->size; tb_memcpy(data, buffer->head, read); buffer->head += read; buffer->size -= read; // null? reset head if (!buffer->size) buffer->head = buffer->data; // ok return read; }
tb_bool_t vm86_parser_get_instruction_name(tb_char_t const** pp, tb_char_t const* e, tb_char_t* name, tb_size_t maxn) { // check tb_assert(pp && e && name && maxn); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // save base tb_char_t const* b = p; // skip name while (p < e && tb_isalpha(*p)) p++; tb_check_break(p <= e && p - b < maxn); // not instruction name? if (p < e && !tb_isspace(*p)) break; // save name tb_memcpy(name, b, p - b); // end name[p - b] = '\0'; // skip the space while (p < e && tb_isspace(*p)) p++; // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t vm86_parser_get_variable_name(tb_char_t const** pp, tb_char_t const* e, tb_char_t* name, tb_size_t maxn) { // check tb_assert(pp && e && name && maxn); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // save base tb_char_t const* b = p; // check tb_check_break(p < e && (tb_isalpha(*p) || *p == '_')); p++; // get name while (p < e && (tb_isalpha(*p) || *p == '_' || tb_isdigit(*p))) p++; tb_check_break(p <= e && p - b < maxn); tb_memcpy(name, b, p - b); // end name[p - b] = '\0'; // skip the space while (p < e && tb_isspace(*p)) p++; // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
tb_byte_t* tb_buffer_memncat(tb_buffer_t* buffer, tb_byte_t const* b, tb_size_t n) { // check tb_assert_and_check_return_val(buffer && b, tb_null); // check tb_check_return_val(n, tb_buffer_data(buffer)); // is null? tb_size_t p = tb_buffer_size(buffer); if (!p) return tb_buffer_memncpy(buffer, b, n); // resize tb_byte_t* d = tb_buffer_resize(buffer, p + n); tb_assert_and_check_return_val(d, tb_null); // memcat tb_memcpy(d + p, b, n); // ok? return d; }
tb_long_t tb_queue_buffer_writ(tb_queue_buffer_t* buffer, tb_byte_t const* data, tb_size_t size) { // check tb_assert_and_check_return_val(buffer && data && buffer->maxn, -1); // no data? if (!buffer->data) { // make data buffer->data = tb_malloc_bytes(buffer->maxn); tb_assert_and_check_return_val(buffer->data, -1); // init it buffer->head = buffer->data; buffer->size = 0; } tb_assert_and_check_return_val(buffer->data && buffer->head, -1); // no left? tb_size_t left = buffer->maxn - buffer->size; tb_check_return_val(left, 0); // move data to head if (buffer->head != buffer->data) { if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size); buffer->head = buffer->data; } // writ data tb_size_t writ = left > size? size : left; tb_memcpy(buffer->data + buffer->size, data, writ); buffer->size += writ; // ok return writ; }
static tb_void_t tb_ifaddrs_interface_load4(tb_list_ref_t interfaces) { // check tb_assert_and_check_return(interfaces); // done PIP_ADAPTER_INFO adapter_info = tb_null; do { // make the adapter info adapter_info = tb_malloc0_type(IP_ADAPTER_INFO); tb_assert_and_check_break(adapter_info); // get the real adapter info size ULONG size = sizeof(IP_ADAPTER_INFO); if (tb_iphlpapi()->GetAdaptersInfo(adapter_info, &size) == ERROR_BUFFER_OVERFLOW) { // grow the adapter info buffer adapter_info = (PIP_ADAPTER_INFO)tb_ralloc(adapter_info, size); tb_assert_and_check_break(adapter_info); // reclear it tb_memset(adapter_info, 0, size); } // get the adapter info if (tb_iphlpapi()->GetAdaptersInfo(adapter_info, &size) != NO_ERROR) break; // done PIP_ADAPTER_INFO adapter = adapter_info; while (adapter) { // check tb_assert(adapter->AdapterName); /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, adapter->AdapterName); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // save flags if (adapter->Type == MIB_IF_TYPE_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; // save hwaddr if (adapter->AddressLength == sizeof(interface->hwaddr.u8)) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; tb_memcpy(interface->hwaddr.u8, adapter->Address, sizeof(interface->hwaddr.u8)); } // save ipaddrs PIP_ADDR_STRING ipAddress = &adapter->IpAddressList; while (ipAddress && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) { // done tb_ipaddr_t ipaddr; if ( ipAddress->IpAddress.String && tb_ipaddr_ip_cstr_set(&ipaddr, ipAddress->IpAddress.String, TB_IPADDR_FAMILY_NONE)) { if (ipaddr.family == TB_IPADDR_FAMILY_IPV4) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4; interface->ipaddr4 = ipaddr.u.ipv4; } else if (ipaddr.family == TB_IPADDR_FAMILY_IPV6) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6; interface->ipaddr6 = ipaddr.u.ipv6; } } // the next ipAddress = ipAddress->Next; } // new interface? save it if ( interface == &interface_new && interface->flags) { // save interface name interface->name = tb_strdup(adapter->AdapterName); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } // the next adapter adapter = adapter->Next; } } while (0); // exit the adapter info if (adapter_info) tb_free(adapter_info); adapter_info = tb_null; }
static tb_void_t tb_ifaddrs_interface_load6(tb_list_ref_t interfaces) { // check tb_assert_and_check_return(interfaces); // done PIP_ADAPTER_ADDRESSES addresses = tb_null; do { // make the addresses addresses = (PIP_ADAPTER_ADDRESSES)tb_malloc0_type(IP_ADAPTER_ADDRESSES); tb_assert_and_check_break(addresses); // get the real adapter info size ULONG size = sizeof(IP_ADAPTER_ADDRESSES); if (tb_iphlpapi()->GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_DNS_SERVER, tb_null, addresses, &size) == ERROR_BUFFER_OVERFLOW) { // grow the adapter info buffer addresses = (PIP_ADAPTER_ADDRESSES)tb_ralloc(addresses, size); tb_assert_and_check_break(addresses); // reclear it tb_memset(addresses, 0, size); } // get the addresses if (tb_iphlpapi()->GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_DNS_SERVER, tb_null, addresses, &size) != NO_ERROR) break; // done PIP_ADAPTER_ADDRESSES address = addresses; while (address) { // check tb_assert(address->AdapterName); /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, address->AdapterName); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // save flags if (address->IfType == IF_TYPE_SOFTWARE_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; // save hwaddr if (address->PhysicalAddressLength == sizeof(interface->hwaddr.u8)) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; tb_memcpy(interface->hwaddr.u8, address->PhysicalAddress, sizeof(interface->hwaddr.u8)); } // save ipaddrs PIP_ADAPTER_UNICAST_ADDRESS ipAddress = address->FirstUnicastAddress; while (ipAddress && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) { // done tb_ipaddr_t ipaddr; struct sockaddr_storage* saddr = (struct sockaddr_storage*)ipAddress->Address.lpSockaddr; if (saddr && tb_sockaddr_save(&ipaddr, saddr)) { if (ipaddr.family == TB_IPADDR_FAMILY_IPV4) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4; interface->ipaddr4 = ipaddr.u.ipv4; } else if (ipaddr.family == TB_IPADDR_FAMILY_IPV6) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6; interface->ipaddr6 = ipaddr.u.ipv6; } } // the next ipAddress = ipAddress->Next; } // new interface? save it if ( interface == &interface_new && interface->flags) { // save interface name interface->name = tb_strdup(address->AdapterName); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } // the next address address = address->Next; } } while (0); // exit the addresses if (addresses) tb_free(addresses); addresses = tb_null; }
tb_iterator_ref_t tb_ifaddrs_itor(tb_ifaddrs_ref_t ifaddrs, tb_bool_t reload) { // check tb_list_ref_t interfaces = (tb_list_ref_t)ifaddrs; tb_assert_and_check_return_val(interfaces, tb_null); // uses the cached interfaces? tb_check_return_val(reload, (tb_iterator_ref_t)interfaces); // clear interfaces first tb_list_clear(interfaces); // query the list of interfaces. struct ifaddrs* list = tb_null; if (!getifaddrs(&list) && list) { #if 0 // init sock tb_long_t sock = socket(AF_INET, SOCK_DGRAM, 0); #endif // done struct ifaddrs* item = tb_null; for (item = list; item; item = item->ifa_next) { // check tb_check_continue(item->ifa_addr && item->ifa_name); /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, item->ifa_name); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // done switch (item->ifa_addr->sa_family) { case AF_INET: { // the address struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr; // save ipaddr4 tb_ipaddr_t ipaddr4; if (!tb_sockaddr_save(&ipaddr4, addr)) break; interface->ipaddr4 = ipaddr4.u.ipv4; // save flags interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4; if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr4)) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; #if 0 // no hwaddr? get it if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)) { // attempt get the hwaddr struct ifreq ifr; tb_memset(&ifr, 0, sizeof(ifr)); tb_strcpy(ifr.ifr_name, item->ifa_name); if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) { // have hwaddr interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; // save hwaddr tb_memcpy(interface->hwaddr.u8, ifr.ifr_hwaddr.sa_data, sizeof(interface->hwaddr.u8)); } } #endif // new interface? save it if (interface == &interface_new) { // save interface name interface->name = tb_strdup(item->ifa_name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } break; case AF_INET6: { // the address struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr; // save ipaddr6 tb_ipaddr_t ipaddr6; if (!tb_sockaddr_save(&ipaddr6, addr)) break; interface->ipaddr6 = ipaddr6.u.ipv6; // save flags interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6; if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr6)) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; #if 0 // no hwaddr? get it if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)) { // attempt get the hwaddr struct ifreq ifr; tb_memset(&ifr, 0, sizeof(ifr)); tb_strcpy(ifr.ifr_name, item->ifa_name); if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) { // have hwaddr interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; // save hwaddr tb_memcpy(interface->hwaddr.u8, ifr.ifr_hwaddr.sa_data, sizeof(interface->hwaddr.u8)); } } #endif // new interface? save it if (interface == &interface_new) { // save interface name interface->name = tb_strdup(item->ifa_name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } break; case AF_PACKET: { // the address struct sockaddr_ll const* addr = (struct sockaddr_ll const*)item->ifa_addr; // check tb_check_break(addr->sll_halen == sizeof(interface->hwaddr.u8)); // no hwaddr? get it if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)) { // have hwaddr interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; // save hwaddr tb_memcpy(interface->hwaddr.u8, addr->sll_addr, sizeof(interface->hwaddr.u8)); // new interface? save it if (interface == &interface_new) { // save interface name interface->name = tb_strdup(item->ifa_name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } } break; default: { // trace tb_trace_d("unknown family: %d", item->ifa_addr->sa_family); } break; } } #if 0 // exit socket if (sock) close(sock); sock = 0; #endif // exit the interface list freeifaddrs(list); } // ok? return (tb_iterator_ref_t)interfaces; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_path_translate(tb_char_t* path, tb_size_t size, tb_size_t maxn) { // check tb_assert_and_check_return_val(path, 0); // file://? tb_char_t* p = path; if (!tb_strnicmp(p, "file:", 5)) p += 5; // is user directory? else if (path[0] == '~') { // get the home directory tb_char_t home[TB_PATH_MAXN]; tb_size_t home_size = tb_directory_home(home, sizeof(home) - 1); tb_assert_and_check_return_val(home_size, 0); // check the path space tb_size_t path_size = size? size : tb_strlen(path); tb_assert_and_check_return_val(home_size + path_size - 1 < maxn, 0); // move the path and ensure the enough space for the home directory tb_memmov(path + home_size, path + 1, path_size - 1); // copy the home directory tb_memcpy(path, home, home_size); path[home_size + path_size - 1] = '\0'; } // remove repeat separator tb_char_t* q = path; tb_size_t repeat = 0; for (; *p; p++) { if (tb_path_is_separator(*p)) { // save the separator if not exists if (!repeat) *q++ = TB_PATH_SEPARATOR; // repeat it repeat++; } else { // save character *q++ = *p; // clear repeat repeat = 0; } } // remove the tail separator and not root: '/' if (q > path + 1 && *(q - 1) == TB_PATH_SEPARATOR) q--; // end *q = '\0'; // is windows path? if (q > path + 1 && tb_isalpha(path[0]) && path[1] == ':') { // get the upper drive prefix path[0] = tb_toupper(path[0]); // append the drive separator if not exists if (q - path == 2) { *q++ = TB_PATH_SEPARATOR; *q = '\0'; } } // trace tb_trace_d("translate: %s", path); // ok return q - path; }
/*! put impl * * <pre> * init: * * 1(head) * ------------------------- * | | * 4 2 * -------------- ------------- * | | | | * 6(parent) 9 7 8 * --------- * | | * 10(last) (hole) <= 5(val) * after: * * 1(head) * ------------------------- * | | * 4 2 * -------------- ------------- * | | | | * 5(hole) 9 7 8 * --------- * | | * 10(last) 6(last) * </pre> */ tb_void_t tb_heap_put(tb_heap_ref_t heap, tb_cpointer_t data) { // check tb_heap_impl_t* impl = (tb_heap_impl_t*)heap; tb_assert_and_check_return(impl && impl->data); // full? grow it if (impl->size == impl->maxn) { // the maxn tb_size_t maxn = tb_align4(impl->maxn + impl->grow); tb_assert_and_check_return(maxn < TB_HEAD_MAXN); // realloc data impl->data = (tb_byte_t*)tb_ralloc(impl->data, maxn * impl->func.size); tb_assert_and_check_return(impl->data); // must be align by 4-bytes tb_assert_and_check_return(!(((tb_size_t)(impl->data)) & 3)); // clear the grow data tb_memset(impl->data + impl->size * impl->func.size, 0, (maxn - impl->maxn) * impl->func.size); // save maxn impl->maxn = maxn; } // check tb_assert_and_check_return(impl->size < impl->maxn); // init func tb_item_func_comp_t func_comp = impl->func.comp; tb_item_func_data_t func_data = impl->func.data; tb_assert_and_check_return(func_comp && func_data); // walk, (hole - 1) / 2: the parent node of the hole tb_size_t parent = 0; tb_byte_t* head = impl->data; tb_size_t hole = impl->size; tb_size_t step = impl->func.size; switch (step) { #ifndef __tb_small__ case sizeof(tb_uint64_t): { for (parent = (hole - 1) >> 1; hole && (func_comp(&impl->func, func_data(&impl->func, head + parent * step), data) > 0); parent = (hole - 1) >> 1) { // move item: parent => hole *((tb_uint64_t*)(head + hole * step)) = *((tb_uint64_t*)(head + parent * step)); // move node: hole => parent hole = parent; } } break; case sizeof(tb_uint32_t): { for (parent = (hole - 1) >> 1; hole && (func_comp(&impl->func, func_data(&impl->func, head + parent * step), data) > 0); parent = (hole - 1) >> 1) { // move item: parent => hole *((tb_uint32_t*)(head + hole * step)) = *((tb_uint32_t*)(head + parent * step)); // move node: hole => parent hole = parent; } } break; case sizeof(tb_uint16_t): { for (parent = (hole - 1) >> 1; hole && (func_comp(&impl->func, func_data(&impl->func, head + parent * step), data) > 0); parent = (hole - 1) >> 1) { // move item: parent => hole *((tb_uint16_t*)(head + hole * step)) = *((tb_uint16_t*)(head + parent * step)); // move node: hole => parent hole = parent; } } break; case sizeof(tb_uint8_t): { for (parent = (hole - 1) >> 1; hole && (func_comp(&impl->func, func_data(&impl->func, head + parent * step), data) > 0); parent = (hole - 1) >> 1) { // move item: parent => hole *((tb_uint8_t*)(head + hole * step)) = *((tb_uint8_t*)(head + parent * step)); // move node: hole => parent hole = parent; } } break; #endif default: for (parent = (hole - 1) >> 1; hole && (func_comp(&impl->func, func_data(&impl->func, head + parent * step), data) > 0); parent = (hole - 1) >> 1) { // move item: parent => hole tb_memcpy(head + hole * step, head + parent * step, step); // move node: hole => parent hole = parent; } break; } // save data impl->func.dupl(&impl->func, head + hole * step, data); // size++ impl->size++; // check // tb_heap_check(impl); }
/*! remove the impl item * * <pre> * init: * 1(head) * ------------------------- * | | * (hole) 2 * -------------- ------------- * | | | | * 6(smaler) 9 7 8 * --------- ---- (hole) <- * | | | | * 10 16 8 (last)---------------------------------------------> 8 (val) * * * after: * 1(head) * ------------------------- * | | * 6 2 * -------------- ------------- * | | | | * (hole) 9 7 8 * --------- <- * | | | * 10(smaller)16 8 (val) * * * after: * 1(head) * ------------------------- * | | * 6 2 * -------------- ------------- * | | | | * 8 9 7 8 * --------- * | | * 10 16 * * </pre> */ static tb_void_t tb_heap_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_heap_impl_t* impl = (tb_heap_impl_t*)iterator; tb_assert_and_check_return(impl && impl->data && impl->size && itor < impl->size); // init func tb_item_func_comp_t func_comp = impl->func.comp; tb_item_func_data_t func_data = impl->func.data; tb_assert_and_check_return(func_comp && func_data); // walk, 2 * hole + 1: the left child node of hole tb_size_t step = impl->func.size; tb_byte_t* head = impl->data; tb_byte_t* hole = head + itor * step; tb_byte_t* tail = head + impl->size * step; tb_byte_t* last = head + (impl->size - 1) * step; tb_byte_t* child = head + ((itor << 1) + 1) * step; tb_pointer_t data_child = tb_null; tb_pointer_t data_rchild = tb_null; tb_pointer_t data_last = func_data(&impl->func, last); switch (step) { #ifndef __tb_small__ case sizeof(tb_uint64_t): { for (; child < tail; child = head + (((child - head) << 1) + step)) { // the smaller child node data_child = func_data(&impl->func, child); if (child + step < tail && func_comp(&impl->func, data_child, (data_rchild = func_data(&impl->func, child + step))) > 0) { child += step; data_child = data_rchild; } // end? if (func_comp(&impl->func, data_child, data_last) > 0) break; // the smaller child node => hole *((tb_uint64_t*)hole) = *((tb_uint64_t*)child); // move the hole down to it's larger child node hole = child; } } break; case sizeof(tb_uint32_t): { for (; child < tail; child = head + (((child - head) << 1) + step)) { // the smaller child node data_child = func_data(&impl->func, child); if (child + step < tail && func_comp(&impl->func, data_child, (data_rchild = func_data(&impl->func, child + step))) > 0) { child += step; data_child = data_rchild; } // end? if (func_comp(&impl->func, data_child, data_last) > 0) break; // the smaller child node => hole *((tb_uint32_t*)hole) = *((tb_uint32_t*)child); // move the hole down to it's larger child node hole = child; } } break; case sizeof(tb_uint16_t): { for (; child < tail; child = head + (((child - head) << 1) + step)) { // the smaller child node data_child = func_data(&impl->func, child); if (child + step < tail && func_comp(&impl->func, data_child, (data_rchild = func_data(&impl->func, child + step))) > 0) { child += step; data_child = data_rchild; } // end? if (func_comp(&impl->func, data_child, data_last) > 0) break; // the smaller child node => hole *((tb_uint16_t*)hole) = *((tb_uint16_t*)child); // move the hole down to it's larger child node hole = child; } } break; case sizeof(tb_uint8_t): { for (; child < tail; child = head + (((child - head) << 1) + step)) { // the smaller child node data_child = func_data(&impl->func, child); if (child + step < tail && func_comp(&impl->func, data_child, (data_rchild = func_data(&impl->func, child + step))) > 0) { child += step; data_child = data_rchild; } // end? if (func_comp(&impl->func, data_child, data_last) > 0) break; // the smaller child node => hole *((tb_uint8_t*)hole) = *((tb_uint8_t*)child); // move the hole down to it's larger child node hole = child; } } break; #endif default: { for (; child < tail; child = head + (((child - head) << 1) + step)) { // the smaller child node data_child = func_data(&impl->func, child); if (child + step < tail && func_comp(&impl->func, data_child, (data_rchild = func_data(&impl->func, child + step))) > 0) { child += step; data_child = data_rchild; } // end? if (func_comp(&impl->func, data_child, data_last) > 0) break; // the smaller child node => hole tb_memcpy(hole, child, step); // move the hole down to it's larger child node hole = child; } } break; } // the last node => hole if (hole != last) tb_memcpy(hole, last, step); // size-- impl->size--; // check // tb_heap_check(impl); }
static tb_long_t tb_aiop_rtor_select_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout) { // check tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor; tb_assert_and_check_return_val(impl && rtor->aiop && list && maxn, -1); // the aiop tb_aiop_impl_t* aiop = rtor->aiop; tb_assert_and_check_return_val(aiop, tb_false); // init time struct timeval t = {0}; if (timeout > 0) { #ifdef TB_CONFIG_OS_WINDOWS t.tv_sec = (LONG)(timeout / 1000); #else t.tv_sec = (timeout / 1000); #endif t.tv_usec = (timeout % 1000) * 1000; } // loop tb_long_t wait = 0; tb_bool_t stop = tb_false; tb_hong_t time = tb_mclock(); while (!wait && !stop && (timeout < 0 || tb_mclock() < time + timeout)) { // enter tb_spinlock_enter(&impl->lock.pfds); // init fdo tb_size_t sfdm = impl->sfdm; tb_memcpy(&impl->rfdo, &impl->rfdi, sizeof(fd_set)); tb_memcpy(&impl->wfdo, &impl->wfdi, sizeof(fd_set)); // leave tb_spinlock_leave(&impl->lock.pfds); // wait #ifdef TB_CONFIG_OS_WINDOWS tb_long_t sfdn = tb_ws2_32()->select((tb_int_t)sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null); #else tb_long_t sfdn = select(sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null); #endif tb_assert_and_check_return_val(sfdn >= 0, -1); // timeout? tb_check_return_val(sfdn, 0); // enter tb_spinlock_enter(&impl->lock.hash); // sync tb_size_t itor = tb_iterator_head(impl->hash); tb_size_t tail = tb_iterator_tail(impl->hash); for (; itor != tail && wait >= 0 && (tb_size_t)wait < maxn; itor = tb_iterator_next(impl->hash, itor)) { tb_hash_map_item_ref_t item = (tb_hash_map_item_ref_t)tb_iterator_item(impl->hash, itor); if (item) { // the sock tb_socket_ref_t sock = (tb_socket_ref_t)item->name; tb_assert_and_check_return_val(sock, -1); // spak? if (sock == aiop->spak[1] && FD_ISSET(((tb_long_t)aiop->spak[1] - 1), &impl->rfdo)) { // read spak tb_char_t spak = '\0'; if (1 != tb_socket_recv(aiop->spak[1], (tb_byte_t*)&spak, 1)) wait = -1; // killed? if (spak == 'k') wait = -1; tb_check_break(wait >= 0); // stop to wait stop = tb_true; // continue it continue ; } // filter spak tb_check_continue(sock != aiop->spak[1]); // the fd tb_long_t fd = (tb_long_t)item->name - 1; // the aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)item->data; tb_assert_and_check_return_val(aioo && aioo->sock == sock, -1); // init aioe tb_aioe_t aioe = {0}; aioe.priv = aioo->priv; aioe.aioo = (tb_aioo_ref_t)aioo; if (FD_ISSET(fd, &impl->rfdo)) { aioe.code |= TB_AIOE_CODE_RECV; if (aioo->code & TB_AIOE_CODE_ACPT) aioe.code |= TB_AIOE_CODE_ACPT; } if (FD_ISSET(fd, &impl->wfdo)) { aioe.code |= TB_AIOE_CODE_SEND; if (aioo->code & TB_AIOE_CODE_CONN) aioe.code |= TB_AIOE_CODE_CONN; } // ok? if (aioe.code) { // save aioe list[wait++] = aioe; // oneshot? clear it if (aioo->code & TB_AIOE_CODE_ONESHOT) { // clear aioo aioo->code = TB_AIOE_CODE_NONE; aioo->priv = tb_null; // clear events tb_spinlock_enter(&impl->lock.pfds); FD_CLR(fd, &impl->rfdi); FD_CLR(fd, &impl->wfdi); tb_spinlock_leave(&impl->lock.pfds); } } } } // leave tb_spinlock_leave(&impl->lock.hash); } // ok return wait; }
tb_byte_t* tb_buffer_resize(tb_buffer_t* buffer, tb_size_t size) { // check tb_assert_and_check_return_val(buffer && size, tb_null); // done tb_bool_t ok = tb_false; tb_byte_t* buff_data = buffer->data; tb_size_t buff_size = buffer->size; tb_size_t buff_maxn = buffer->maxn; do { // check tb_assert_and_check_break(buff_data); // using static buffer? if (buff_data == buffer->buff) { // grow? if (size > buff_maxn) { // grow maxn buff_maxn = tb_align8(size + TB_BUFFER_GROW_SIZE); tb_assert_and_check_break(size <= buff_maxn); // grow data buff_data = tb_malloc_bytes(buff_maxn); tb_assert_and_check_break(buff_data); // copy data tb_memcpy(buff_data, buffer->buff, buff_size); } // update the size buff_size = size; } else { // grow? if (size > buff_maxn) { // grow maxn buff_maxn = tb_align8(size + TB_BUFFER_GROW_SIZE); tb_assert_and_check_break(size <= buff_maxn); // grow data buff_data = (tb_byte_t*)tb_ralloc(buff_data, buff_maxn); tb_assert_and_check_break(buff_data); } #if 0 // decrease to the static buffer else if (size <= sizeof(buffer->buff)) { // update the maxn buff_maxn = sizeof(buffer->buff); // copy data tb_memcpy(buffer->buff, buff_data, size); // free data tb_free(buff_data); // using the static buffer buff_data = buffer->buff; } #endif // update the size buff_size = size; } // update the buffer buffer->data = buff_data; buffer->size = buff_size; buffer->maxn = buff_maxn; // ok ok = tb_true; } while (0); // trace if (!ok) tb_trace_e("resize buffer failed: %lu => %lu", buff_size, size); // ok return ok? (tb_byte_t*)buffer->data : tb_null; }