diff --git a/binding/c/ip2region.c b/binding/c/ip2region.c index c20d88e..87e0ed0 100644 --- a/binding/c/ip2region.c +++ b/binding/c/ip2region.c @@ -35,12 +35,15 @@ IP2R_API uint_t ip2region_create(ip2region_t ip2rObj, char *dbFile) if ( ip2rObj->dbHandler == NULL ) { IP2R_FREE(ip2rObj->HeaderSip); IP2R_FREE(ip2rObj->HeaderPtr); + //fprintf(stderr, "Fail to open the db file %s\n", ip2rObj>dbFile); + //exit(-1); return 0; } ip2rObj->firstIndexPtr = 0; ip2rObj->lastIndexPtr = 0; ip2rObj->totalBlocks = 0; + ip2rObj->dbBinStr = NULL; return 1; } @@ -63,9 +66,94 @@ IP2R_API uint_t ip2region_destroy(ip2region_t ip2rObj) ip2rObj->dbHandler = NULL; } + //free the db binary string + if ( ip2rObj->dbBinStr != NULL ) { + IP2R_FREE(ip2rObj->dbBinStr); + ip2rObj->dbBinStr = NULL; + } + return 1; } +/** + * get the region associated with the specified ip address with the memory binary search algorithm + * + * @param ip2rObj + * @param ip + * @param datablock +*/ +IP2R_API uint_t ip2region_memory_search(ip2region_t ip2rObj, uint_t ip, datablock_t datablock) +{ + int l, h, m, p; + uint_t sip, eip, dptr; + int dataLen, dataptr; + long filesize; + char *buffer; + + if ( ip2rObj->dbBinStr == NULL ) { + //get the size of the file + fseek(ip2rObj->dbHandler, 0, SEEK_END); + filesize = ftell(ip2rObj->dbHandler); + fseek(ip2rObj->dbHandler, 0, SEEK_SET); + + //alloc the buffer size + ip2rObj->dbBinStr = IP2R_MALLOC(filesize); + if ( ip2rObj->dbBinStr == NULL ) { + return 0; + } + + //now read the whole file + if ( fread(ip2rObj->dbBinStr, filesize, 1, ip2rObj->dbHandler) != 1 ) { + return 0; + } + + buffer = ip2rObj->dbBinStr; + ip2rObj->firstIndexPtr = getUnsignedInt(buffer, 0); + ip2rObj->lastIndexPtr = getUnsignedInt(buffer, 4); + ip2rObj->totalBlocks = (ip2rObj->lastIndexPtr-ip2rObj->firstIndexPtr)/INDEX_BLOCK_LENGTH + 1; + } + + l = 0; h = ip2rObj->totalBlocks; dptr = 0; + while ( l <= h ) { + m = (l + h) >> 1; + p = ip2rObj->firstIndexPtr + m * INDEX_BLOCK_LENGTH; + + buffer = ip2rObj->dbBinStr + p; + sip = getUnsignedInt(buffer, 0); + if ( ip < sip ) { + h = m - 1; + } else { + eip = getUnsignedInt(buffer, 4); + if ( ip > eip ) { + l = m + 1; + } else { + dptr = getUnsignedInt(buffer, 8); + break; + } + } + } + + if ( dptr == 0 ) return 0; + + //get the data + dataLen = ((dptr >> 24) & 0xFF); + dataptr = (dptr & 0x00FFFFFF); + buffer = ip2rObj->dbBinStr + dataptr; + + //fill the data to the datablock + datablock->city_id = getUnsignedInt(buffer, 0); + dataLen -= 4; //reduce the length of the city_id + memcpy(datablock->region, buffer + 4, dataLen); + datablock->region[dataLen] = '\0'; + + return 1; +} + +IP2R_API uint_t ip2region_memory_search_string(ip2region_t ip2rObj, char *ip, datablock_t datablock) +{ + return ip2region_memory_search(ip2rObj, ip2long(ip), datablock); +} + /** * get the region associated with the specifield ip address with binary search algorithm * diff --git a/binding/c/ip2region.h b/binding/c/ip2region.h index bf7eac7..33820b3 100644 --- a/binding/c/ip2region.h +++ b/binding/c/ip2region.h @@ -52,7 +52,9 @@ typedef struct { uint_t *HeaderSip; //header start ip blocks uint_t *HeaderPtr; //header ptr blocks uint_t headerLen; //header block number + char *dbFile; //path of db file FILE *dbHandler; //file handler + char *dbBinStr; //db binary string for memory search mode uint_t firstIndexPtr; //first index ptr uint_t lastIndexPtr; //last index ptr @@ -79,14 +81,26 @@ typedef datablock_entry * datablock_t; IP2R_API uint_t ip2region_create(ip2region_t, char *); /** - * destroy the specifield ip2region object + * destroy the specified ip2region object * * @param ip2region_t */ IP2R_API uint_t ip2region_destroy(ip2region_t); /** - * get the region associated with the specifield ip address with binary search algorithm + * get the region associated with the specified ip address with the memory binary search algorithm + * + * @param ip2region_t + * @param uint_t + * @param datablock_t + * @date 2016/06/30 +*/ +IP2R_API uint_t ip2region_memory_search(ip2region_t, uint_t, datablock_t); +IP2R_API uint_t ip2region_memory_search_string(ip2region_t, char *, datablock_t); + + +/** + * get the region associated with the specified ip address with binary search algorithm * * @param ip2rObj * @param ip @@ -97,7 +111,7 @@ IP2R_API uint_t ip2region_binary_search(ip2region_t, uint_t, datablock_t); IP2R_API uint_t ip2region_binary_search_string(ip2region_t, char *, datablock_t); /** - * get the region associated with the specifield ip address with b-tree algorithm + * get the region associated with the specified ip address with b-tree algorithm * * @param ip2rObj * @param ip @@ -108,7 +122,7 @@ IP2R_API uint_t ip2region_btree_search(ip2region_t, uint_t, datablock_t); IP2R_API uint_t ip2region_btree_search_string(ip2region_t, char *, datablock_t); /** - * get a unsinged long(4bytes) from a specifield buffer start from the specifield offset + * get a unsinged long(4bytes) from a specified buffer start from the specified offset * * @param buffer * @param offset diff --git a/binding/c/testSearcher.c b/binding/c/testSearcher.c index d5d8e32..a7661a7 100644 --- a/binding/c/testSearcher.c +++ b/binding/c/testSearcher.c @@ -54,22 +54,27 @@ int main( int argc, char **argv ) memset(&datablock, 0x00, sizeof(datablock_entry)); if ( argc < 2 ) { - printf("Usage: a.out [ip2region db file path] [algorithm]"); + printf("Usage: a.out [ip2region db file path] [algorithm]\n"); return 0; } dbFile = argv[1]; algorithm = "B-tree"; func_ptr = ip2region_btree_search_string; - if ( argc >= 3 && strcmp(argv[2], "binary") == 0 ) { - algorithm = "Binary"; - func_ptr = ip2region_binary_search_string; + if ( argc >= 3 ) { + if ( strcmp(argv[2], "binary") == 0 ) { + algorithm = "Binary"; + func_ptr = ip2region_binary_search_string; + } else if ( strcmp(argv[2], "memory") == 0 ) { + algorithm = "Memory"; + func_ptr = ip2region_memory_search_string; + } } //create a new ip2rObj printf("+--initializing %s ... \n", algorithm); if ( ip2region_create(&ip2rEntry, dbFile) == 0 ) { - println("Error: Fail to create the ip2region object"); + println("Error: Fail to create the ip2region object\n"); return 0; }