From f5d0c216c2d588a2491879dc4e2685e67aec3542 Mon Sep 17 00:00:00 2001 From: lion Date: Mon, 27 Jun 2022 18:32:40 +0800 Subject: [PATCH] add the clang xdb searcher binding --- .gitignore | 1 + binding/c/CMakeLists.txt | 7 +++ binding/c/util_test.c | 39 +++++++++++++ binding/c/xdb_searcher.c | 116 +++++++++++++++++++++++++++++++++++++++ binding/c/xdb_searcher.h | 87 +++++++++++++++++++++++++++++ 5 files changed, 250 insertions(+) create mode 100644 binding/c/CMakeLists.txt create mode 100644 binding/c/util_test.c create mode 100644 binding/c/xdb_searcher.c create mode 100644 binding/c/xdb_searcher.h diff --git a/.gitignore b/.gitignore index acdba36..ccbd533 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ META-INF/ /binding/java/*.jar /binding/c/testSearcher +/binding/c/cmake-build-debug # golang /binding/golang/searcher diff --git a/binding/c/CMakeLists.txt b/binding/c/CMakeLists.txt new file mode 100644 index 0000000..dbc513d --- /dev/null +++ b/binding/c/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.22) +project(c C) + +set(CMAKE_C_STANDARD 11) + +add_executable(c + xdb_searcher.c xdb_searcher.h) diff --git a/binding/c/util_test.c b/binding/c/util_test.c new file mode 100644 index 0000000..2c502b9 --- /dev/null +++ b/binding/c/util_test.c @@ -0,0 +1,39 @@ +// Copyright 2022 The Ip2Region Authors. All rights reserved. +// Use of this source code is governed by a Apache2.0-style +// license that can be found in the LICENSE file. + +// --- +// @Author Lion +// @Date 2022/06/27 + +#include "stdio.h" +#include "xdb_searcher.h" + +int main(int argc, char *argv[]) { + char *ip_list[] = { + "1.2.3.4", "192.168.2.3", "120.24.78.129", "255.255.255.0", + "256.7.12.9", "12.56.78.320", "32.12.45.192", "222.221.220.219", + "192.168.1.101 ", "132.96.12.98a", "x23.12.2.12" + }; + + int errcode, i; + unsigned int ip; + char ip_buff[16] = {'\0'}; + for (i = 0; i < 11; i++) { + errcode = check_ip(ip_list[i], &ip); + if (errcode != 0) { + printf("invalid ip address `%s`\n", ip_list[i]); + continue; + } + + long2ip(ip, ip_buff); + printf("long(%-15s)=%-10u, long2ip(%-10u)=%-15s", ip_list[i], ip, ip, ip_buff); + if (strcmp(ip_list[i], ip_buff) != 0) { + printf(" --[Failed]\n"); + } else { + printf(" --[Ok]\n"); + } + } + + return 0; +} \ No newline at end of file diff --git a/binding/c/xdb_searcher.c b/binding/c/xdb_searcher.c new file mode 100644 index 0000000..692f15d --- /dev/null +++ b/binding/c/xdb_searcher.c @@ -0,0 +1,116 @@ +// Copyright 2022 The Ip2Region Authors. All rights reserved. +// Use of this source code is governed by a Apache2.0-style +// license that can be found in the LICENSE file. + +// --- +// @Author Lion +// @Date 2022/06/27 + +#include "xdb_searcher.h" + +XDB_PRIVATE(int) xdb_new_base(xdb_searcher_t *xdb, const char *dbPath, const char *vIndex, const char *cBuff) { + memset(xdb, 0x00, sizeof(xdb_searcher_t)); + + // check the content buffer first + if (cBuff != NULL) { + xdb->vector_index = NULL; + xdb->content_buff = cBuff; + return 0; + } + + // open the xdb binary file + FILE *handle = fopen(dbPath, "r"); + if (handle == NULL) { + return 1; + } + + xdb->handle = handle; + xdb->vector_index = vIndex; + + return 0; +} + +// xdb searcher new api define +XDB_PUBLIC(int) xdb_new_with_file_only(xdb_searcher_t *xdb, char *dbPath) { + return xdb_new_base(xdb, dbPath, NULL, NULL); +} + +XDB_PUBLIC(int) xdb_new_with_vector_index(xdb_searcher_t *xdb, char *dbPath, char *vIndex) { + return xdb_new_base(xdb, dbPath, vIndex, NULL); +} + +XDB_PUBLIC(int) xdb_new_with_buffer(xdb_searcher_t *xdb, char *cBuff) { + return xdb_new_base(xdb, NULL, NULL, cBuff); +} + +XDB_PUBLIC(void) xdb_close(xdb_searcher_t *xdb) { + if (xdb->handle != NULL) { + fclose(xdb->handle); + } +} + +// xdb searcher search api define +XDB_PUBLIC(int) xdb_search(unsigned int ip, char *buffer) { + return 0; +} + +XDB_PUBLIC(int) xdb_search_by_string(const char *ip, char *buffer) { + return 0; +} + +// get unsigned long (4bytes) from a specified buffer start from the specified offset +XDB_PUBLIC(unsigned int) get_unsigned_int(const char *buffer, int offset) { + return ( + ((buffer[offset ]) & 0x000000FF) | + ((buffer[offset+1] << 8) & 0x0000FF00) | + ((buffer[offset+2] << 16) & 0x00FF0000) | + ((buffer[offset+3] << 24) & 0xFF000000) + ); +} + +// get unsigned short (2bytes) from a specified buffer start from the specified offset +XDB_PUBLIC(unsigned int) get_unsigned_short(const char *buffer, int offset) { + return ( + ((buffer[offset ]) & 0x000000FF) | + ((buffer[offset+1] << 8) & 0x0000FF00) + ); +} + +// string ip to unsigned int +static int shiftIndex[4] = {24, 16, 8, 0}; +XDB_PUBLIC(int) check_ip(const char *src_ip, unsigned int *dst_ip) { + char c; + int i, n, ip = 0; + const char *ptr = src_ip; + for (i = 0; i < 4; i++) { + n = 0; + while (1) { + c = *ptr; + ptr++; + if (c >= '0' && c <= '9') { + n *= 10; + n += c - '0'; + } else if ((i < 3 && c == '.') || i == 3) { + // stopping at the '.' but ignore the tailing chars + // after the 3rd one (auto clean the tailing none-integer ?). + break; + } else { + return 1; + } + } + + if (n > 0xFF) { + return 2; + } + + ip |= (n << shiftIndex[i]); + } + + *dst_ip = ip; + return 0; +} + +// unsigned int ip to string ip +XDB_PUBLIC(void) long2ip(unsigned int ip, char *buffer) { + sprintf(buffer, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); +} \ No newline at end of file diff --git a/binding/c/xdb_searcher.h b/binding/c/xdb_searcher.h new file mode 100644 index 0000000..45abe38 --- /dev/null +++ b/binding/c/xdb_searcher.h @@ -0,0 +1,87 @@ +// Copyright 2022 The Ip2Region Authors. All rights reserved. +// Use of this source code is governed by a Apache2.0-style +// license that can be found in the LICENSE file. + +// --- +// @Author Lion +// @Date 2022/06/27 + +#ifndef C_XDB_SEARCHER_H +#define C_XDB_SEARCHER_H + +#include +#include +#include + +#if ( defined(WIN32) || defined(_WIN32) || defined(__WINDOWS_) || defined(WINNT) ) +# define XDB_PUBLIC(type) extern __declspec(dllexport) type +# define XDB_PRIVATE(type) static type +# define XDB_WINDOWS +#elif ( defined(linux) || defined(_UNIX) ) +# define XDB_PUBLIC(type) extern type +# define XDB_PRIVATE(type) static inline type +# define XDB_LINUX +#endif + +// memory allocation error +#define XDB_ALLOCATE_ERROR(func, bytes) \ +do { \ + printf(": Allocate Error In Function <%s> For %lu Bytes.\n", func, (unsigned long int) bytes); \ + return NULL; \ +} while (0); + + +#define xdb_calloc( _blocks, _bytes ) calloc( _blocks, _bytes ) +#define xdb_malloc( _bytes ) malloc( _bytes ) +#define xdb_free( _ptr ) free( _ptr ) +#define field_size(type, field) sizeof(((type *)0)->field) +#define sf_field_size(type, field) (sizeof(((type *)0)->field) - 1) + +// xdb searcher structure +struct xdb_searcher_entry { + FILE *handle; + + // header info + const char *header; + int io_count; + + // vector index buffer cache. + // preload the vector index will reduce the number of IO operations + // thus speedup the search process. + const char *vector_index; + + // content buffer. + // cache the whole xdb content. + const char *content_buff; +}; +typedef struct xdb_searcher_entry xdb_searcher_t; + +// xdb searcher new api define +XDB_PUBLIC(int) xdb_new_with_file_only(xdb_searcher_t *, char *); + +XDB_PUBLIC(int) xdb_new_with_vector_index(xdb_searcher_t *, char *, char *); + +XDB_PUBLIC(int) xdb_new_with_buffer(xdb_searcher_t *, char *); + +XDB_PUBLIC(void) xdb_close(xdb_searcher_t *); + +// xdb searcher search api define +XDB_PUBLIC(int) xdb_search(unsigned int, char *); + +XDB_PUBLIC(int) xdb_search_by_string(const char *, char *); + + +// get unsigned long (4bytes) from a specified buffer start from the specified offset with little-endian +XDB_PUBLIC(unsigned int) get_unsigned_int(const char *, int); + +// get unsigned short (2bytes) from a specified buffer start from the specified offset with little-endian +XDB_PUBLIC(unsigned int) get_unsigned_short(const char *, int); + +// check the specified string ip and convert it to an unsigned int +XDB_PUBLIC(int) check_ip(const char *, unsigned int *); + +// unsigned int ip to string ip +XDB_PUBLIC(void) long2ip(unsigned int, char *); + + +#endif //C_XDB_SEARCHER_H