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_demo_small_allocator_underflow2() { // done tb_allocator_ref_t small_allocator = tb_null; do { // init small allocator small_allocator = tb_small_allocator_init(tb_null); tb_assert_and_check_break(small_allocator); // make data tb_pointer_t data = tb_allocator_malloc(small_allocator, 10); tb_assert_and_check_break(data); // done underflow tb_memset(data, 0, 10 + 1); // make data2 data = tb_allocator_malloc(small_allocator, 10); tb_assert_and_check_break(data); #ifdef __tb_debug__ // dump small_allocator tb_allocator_dump(small_allocator); #endif } while (0); // exit small allocator if (small_allocator) tb_allocator_exit(small_allocator); small_allocator = tb_null; }
static tb_long_t tb_ifaddrs_netlink_socket_send(tb_long_t sock, tb_long_t request) { // check tb_assert_and_check_return_val(sock >= 0, -1); // init packet struct { struct nlmsghdr m_hdr; struct rtgenmsg m_msg; } packet; tb_memset(&packet, 0, sizeof(packet)); packet.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); packet.m_hdr.nlmsg_type = (tb_int_t)request; packet.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; packet.m_hdr.nlmsg_pid = 0; packet.m_hdr.nlmsg_seq = (tb_int_t)sock; packet.m_msg.rtgen_family = AF_UNSPEC; // send packet struct sockaddr_nl addr; memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; return sendto(sock, &packet.m_hdr, packet.m_hdr.nlmsg_len, 0, (struct sockaddr *)&addr, sizeof(addr)); }
static tb_void_t tb_element_uint8_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size) { // check tb_assert_and_check_return(buff); // copy elements tb_memset(buff, tb_p2u8(data), size); }
tb_void_t tb_sockdata_clear(tb_sockdata_ref_t sockdata) { // check tb_assert(sockdata); // clear data if (sockdata->data) tb_memset(sockdata->data, 0, sockdata->maxn * sizeof(tb_cpointer_t)); }
tb_void_t tb_queue_buffer_exit(tb_queue_buffer_ref_t buffer) { if (buffer) { if (buffer->data) tb_free(buffer->data); tb_memset(buffer, 0, sizeof(tb_queue_buffer_t)); } }
/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_void_t tb_hwaddr_clear(tb_hwaddr_ref_t hwaddr) { // check tb_assert_and_check_return(hwaddr); // clear it tb_memset(hwaddr->u8, 0, sizeof(hwaddr->u8)); }
static tb_void_t tb_element_uint8_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size) { // check tb_assert_and_check_return(buff); // clear elements if (size) tb_memset(buff, 0, size); }
static tb_void_t tb_item_func_uint16_nfree(tb_item_func_t* func, tb_pointer_t buff, tb_size_t size) { // check tb_assert_and_check_return(buff); // clear items if (size) tb_memset(buff, 0, size * sizeof(tb_uint16_t)); }
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 }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_processor_count() { // clear the system info SYSTEM_INFO info; tb_memset(&info, 0, sizeof(SYSTEM_INFO)); // get the system info GetSystemInfo(&info); // the processor count return (tb_size_t)info.dwNumberOfProcessors? info.dwNumberOfProcessors : 1; }
tb_pointer_t tb_pool_align_nalloc0_(tb_pool_ref_t pool, tb_size_t item, tb_size_t size, tb_size_t align __tb_debug_decl__) { // nalloc it tb_pointer_t data = tb_pool_align_nalloc_(pool, item, size, align __tb_debug_args__); tb_assert_and_check_return_val(data, tb_null); // clear it tb_memset(data, 0, item * size); // ok return data; }
static inline void reset_screen(void) { tb_memset(screen, 0, SCREEN_BUFFER); cursor_x = 0; cursor_y = 0; num_lines = 0; outb(CTL_ADDR_REG, START_ADD_HIGH_REG); outb(CTL_DATA_REG, 0x00); outb(CTL_ADDR_REG, START_ADD_LOW_REG); outb(CTL_DATA_REG, 0x00); }
tb_bool_t tb_object_init(tb_object_ref_t object, tb_size_t flag, tb_size_t type) { // check tb_assert_and_check_return_val(object, tb_false); // init tb_memset(object, 0, sizeof(tb_object_t)); object->flag = (tb_uint8_t)flag; object->type = (tb_uint16_t)type; object->refn = 1; // ok return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_zip_vlc_t* tb_zip_vlc_fixed_open(tb_zip_vlc_fixed_t* fixed, tb_byte_t nbits) { // init tb_memset(fixed, 0, sizeof(tb_zip_vlc_fixed_t)); ((tb_zip_vlc_t*)fixed)->type = TB_ZIP_VLC_TYPE_FIXED; ((tb_zip_vlc_t*)fixed)->set = tb_zip_vlc_fixed_set; ((tb_zip_vlc_t*)fixed)->get = tb_zip_vlc_fixed_get; ((tb_zip_vlc_t*)fixed)->clos = tb_null; fixed->nbits = nbits; // check tb_assert_and_check_return_val(nbits <= 32, tb_null); return (tb_zip_vlc_t*)fixed; }
static tb_void_t tb_element_ptr_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size) { // check tb_assert_and_check_return(element && buff); // the free is hooked? free it if (element->free != tb_element_ptr_free && element->free) { tb_size_t n = size; while (n--) element->free(element, (tb_byte_t*)buff + n * sizeof(tb_pointer_t)); } // clear if (size) tb_memset(buff, 0, size * sizeof(tb_pointer_t)); }
static tb_void_t tb_element_str_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size) { // check tb_assert_and_check_return(element && buff); // free elements if (element->free) { tb_size_t n = size; while (n--) element->free(element, (tb_byte_t*)buff + n * sizeof(tb_char_t*)); } // clear if (size) tb_memset(buff, 0, size * sizeof(tb_char_t*)); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_sha_init(tb_sha_t* sha, tb_size_t mode) { // check tb_assert_and_check_return(sha); // init sha tb_memset(sha, 0, sizeof(tb_sha_t)); // done sha->digest_len = (mode >> 5) & 0xff; switch (mode) { case TB_SHA_MODE_SHA1_160: sha->state[0] = 0x67452301; sha->state[1] = 0xefcdab89; sha->state[2] = 0x98badcfe; sha->state[3] = 0x10325476; sha->state[4] = 0xc3d2e1f0; sha->transform = tb_sha_transform_sha1; break; case TB_SHA_MODE_SHA2_224: sha->state[0] = 0xc1059ed8; sha->state[1] = 0x367cd507; sha->state[2] = 0x3070dd17; sha->state[3] = 0xf70e5939; sha->state[4] = 0xffc00b31; sha->state[5] = 0x68581511; sha->state[6] = 0x64f98fa7; sha->state[7] = 0xbefa4fa4; sha->transform = tb_sha_transform_sha2; break; case TB_SHA_MODE_SHA2_256: sha->state[0] = 0x6a09e667; sha->state[1] = 0xbb67ae85; sha->state[2] = 0x3c6ef372; sha->state[3] = 0xa54ff53a; sha->state[4] = 0x510e527f; sha->state[5] = 0x9b05688c; sha->state[6] = 0x1f83d9ab; sha->state[7] = 0x5be0cd19; sha->transform = tb_sha_transform_sha2; break; default: tb_assert(0); break; } sha->count = 0; }
tb_bool_t tb_file_info(tb_char_t const* path, tb_file_info_t* info) { // check tb_assert_and_check_return_val(path, tb_false); // the full path (need translate "~/") tb_char_t full[TB_PATH_MAXN]; path = tb_path_absolute(path, full, TB_PATH_MAXN); tb_assert_and_check_return_val(path, tb_false); // exists? tb_check_return_val(!access(path, F_OK), tb_false); // get info if (info) { // init info tb_memset(info, 0, sizeof(tb_file_info_t)); // get stat #ifdef TB_CONFIG_POSIX_HAVE_STAT64 struct stat64 st = {0}; if (!stat64(path, &st)) #else struct stat st = {0}; if (!stat(path, &st)) #endif { // file type if (S_ISDIR(st.st_mode)) info->type = TB_FILE_TYPE_DIRECTORY; else info->type = TB_FILE_TYPE_FILE; // file size info->size = st.st_size >= 0? (tb_hize_t)st.st_size : 0; // the last access time info->atime = (tb_time_t)st.st_atime; // the last modify time info->mtime = (tb_time_t)st.st_mtime; } } // ok return tb_true; }
tb_byte_t* tb_buffer_memnsetp(tb_buffer_t* buffer, tb_size_t p, tb_byte_t b, tb_size_t n) { // check tb_assert_and_check_return_val(buffer, 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); // memset tb_memset(d + p, b, n); // ok? return d; }
tb_void_t tb_poller_clear(tb_poller_ref_t self) { // check tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self; tb_assert_and_check_return(poller); // clear hash if (poller->hash) tb_memset(poller->hash, 0, poller->hash_size * sizeof(tb_cpointer_t)); // clear pfds if (poller->pfds) tb_vector_clear(poller->pfds); // clear cfds if (poller->cfds) tb_vector_clear(poller->cfds); // spak it if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1); }
tb_void_t tb_hash_map_clear(tb_hash_map_ref_t hash_map) { // check tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)hash_map; tb_assert_and_check_return(impl && impl->hash_list); // step tb_size_t step = impl->element_name.size + impl->element_data.size; tb_assert_and_check_return(step); // clear impl tb_size_t i = 0; tb_size_t n = impl->hash_size; for (i = 0; i < n; i++) { tb_hash_map_item_list_t* list = impl->hash_list[i]; if (list) { // free items if (impl->element_name.free || impl->element_data.free) { tb_size_t j = 0; tb_size_t m = list->size; for (j = 0; j < m; j++) { tb_byte_t* item = ((tb_byte_t*)&list[1]) + j * step; if (impl->element_name.free) impl->element_name.free(&impl->element_name, item); if (impl->element_data.free) impl->element_data.free(&impl->element_data, item + impl->element_name.size); } } // free list tb_free(list); } impl->hash_list[i] = tb_null; } // reset info impl->item_size = 0; impl->item_maxn = 0; tb_memset(&impl->item, 0, sizeof(tb_hash_map_item_t)); }
static tb_void_t tb_poller_hash_set(tb_poller_poll_ref_t poller, tb_socket_ref_t sock, tb_cpointer_t priv) { // check tb_assert(poller && sock); // the socket fd tb_long_t fd = tb_sock2fd(sock); tb_assert(fd > 0 && fd < TB_MAXS32); // not null? if (priv) { // no hash? init it first tb_size_t need = fd + 1; if (!poller->hash) { // init hash poller->hash = tb_nalloc0_type(need, tb_cpointer_t); tb_assert_and_check_return(poller->hash); // init hash size poller->hash_size = need; } else if (need > poller->hash_size) { // grow hash poller->hash = (tb_cpointer_t*)tb_ralloc(poller->hash, need * sizeof(tb_cpointer_t)); tb_assert_and_check_return(poller->hash); // init growed space tb_memset(poller->hash + poller->hash_size, 0, (need - poller->hash_size) * sizeof(tb_cpointer_t)); // grow hash size poller->hash_size = need; } // save the user private data poller->hash[fd] = priv; } }
tb_void_t tb_sockdata_insert(tb_sockdata_ref_t sockdata, tb_socket_ref_t sock, tb_cpointer_t priv) { // check tb_long_t fd = tb_sock2fd(sock); tb_assert(sockdata && fd > 0 && fd < TB_MAXS32); // not null? if (priv) { // no data? init it first tb_size_t need = fd + 1; if (!sockdata->data) { // init data need += TB_SOCKDATA_GROW; sockdata->data = tb_nalloc0_type(need, tb_cpointer_t); tb_assert_and_check_return(sockdata->data); // init data size sockdata->maxn = need; } else if (need > sockdata->maxn) { // grow data need += TB_SOCKDATA_GROW; sockdata->data = (tb_cpointer_t*)tb_ralloc(sockdata->data, need * sizeof(tb_cpointer_t)); tb_assert_and_check_return(sockdata->data); // init growed space tb_memset(sockdata->data + sockdata->maxn, 0, (need - sockdata->maxn) * sizeof(tb_cpointer_t)); // grow data size sockdata->maxn = need; } // save the socket private data sockdata->data[fd] = priv; } }
tb_bool_t tb_vector_resize(tb_vector_ref_t vector, tb_size_t size) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)vector; tb_assert_and_check_return_val(impl, tb_false); // free items if the impl is decreased if (size < impl->size) { // free data if (impl->func.nfree) impl->func.nfree(&impl->func, impl->data + size * impl->func.size, impl->size - size); } // resize buffer if (size > impl->maxn) { tb_size_t maxn = tb_align4(size + impl->grow); tb_assert_and_check_return_val(maxn < TB_VECTOR_MAXN, tb_false); // realloc data impl->data = (tb_byte_t*)tb_ralloc(impl->data, maxn * impl->func.size); tb_assert_and_check_return_val(impl->data, tb_false); // must be align by 4-bytes tb_assert_and_check_return_val(!(((tb_size_t)(impl->data)) & 3), tb_false); // 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; } // update size impl->size = size; return tb_true; }
tb_context_ref_t tb_context_init(tb_byte_t* data, tb_size_t size) { // check size tb_size_t context_size = tb_context_size(); tb_assert_and_check_return_val(data && context_size && context_size <= size, tb_null); // get context tb_context_ref_t context = (tb_context_ref_t)data; // init context tb_memset(data, 0, context_size); #if defined(TB_CONFIG_POSIX_HAVE_GETCONTEXT) && \ defined(TB_CONFIG_POSIX_HAVE_SETCONTEXT) && \ defined(TB_CONFIG_POSIX_HAVE_MAKECONTEXT) // init sigmask sigset_t zero; sigemptyset(&zero); sigprocmask(SIG_BLOCK, &zero, &((ucontext_t*)context)->uc_sigmask); #endif // ok return context; }
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; }
/*! 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); }
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; }