-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
321 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
#pragma once | ||
|
||
#include <stdlib.h> | ||
#include <time.h> | ||
#include <math.h> | ||
|
||
//g - group,7位(0~127) | ||
//i - index,12位(0~4095) | ||
//s - 序号,14位(0~17823) | ||
//ts - 时间戳,30位 | ||
//共63位,防止出现负数 | ||
|
||
namespace luakit { | ||
|
||
const uint32_t GROUP_BITS = 7; | ||
const uint32_t INDEX_BITS = 12; | ||
const uint32_t SNUM_BITS = 14; | ||
|
||
const uint32_t LETTER_LEN = 12; | ||
const uint32_t LETTER_SIZE = 62; | ||
|
||
//基准时钟:2022-10-01 08:00:00 | ||
const uint32_t BASE_TIME = 1664582400; | ||
|
||
const uint32_t MAX_GROUP = ((1 << GROUP_BITS) - 1); //128 - 1 | ||
const uint32_t MAX_INDEX = ((1 << INDEX_BITS) - 1); //4096 - 1 | ||
const uint32_t MAX_SNUM = ((1 << SNUM_BITS) - 1); //17824 - 1 - FULL_NUM | ||
|
||
//每一group独享一个id生成种子 | ||
thread_local time_t last_time = 0; | ||
thread_local size_t serial_inedx_table[(1 << GROUP_BITS)] = { 0 }; | ||
|
||
static char letter[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | ||
|
||
inline uint64_t guid_new(uint32_t group, uint32_t index){ | ||
if (group == 0) { | ||
group = rand(); | ||
} | ||
if (index == 0) { | ||
index = rand(); | ||
} | ||
group %= MAX_GROUP; | ||
index %= MAX_INDEX; | ||
time_t now_time; | ||
time(&now_time); | ||
size_t serial_index; | ||
if (now_time <= last_time) { | ||
serial_index = ++serial_inedx_table[group]; | ||
//种子溢出以后,时钟往前推 | ||
if (serial_index >= MAX_SNUM) { | ||
serial_inedx_table[group] = 0; | ||
last_time = ++now_time; | ||
serial_index = 0; | ||
} | ||
} | ||
else { | ||
serial_inedx_table[group] = 0; | ||
last_time = now_time; | ||
} | ||
return ((last_time - BASE_TIME) << (SNUM_BITS + GROUP_BITS + INDEX_BITS)) | | ||
(serial_index << (GROUP_BITS + INDEX_BITS)) | (index << GROUP_BITS) | group; | ||
} | ||
|
||
inline int guid_string(lua_State* L, uint32_t group, uint32_t index) { | ||
char sguid[32]; | ||
size_t guid = guid_new(group, index); | ||
snprintf(sguid, 32, "%zu", guid); | ||
lua_pushstring(L, sguid); | ||
return 1; | ||
} | ||
|
||
inline int guid_hex(lua_State* L, uint32_t group, uint32_t index) { | ||
char sguid[32]; | ||
size_t guid = guid_new(group, index); | ||
snprintf(sguid, 32, "%016lx", guid); | ||
lua_pushstring(L, sguid); | ||
return 1; | ||
} | ||
|
||
inline int guid_tostring(lua_State* L, uint64_t guid) { | ||
char sguid[32]; | ||
snprintf(sguid, 32, "%zu", guid); | ||
lua_pushstring(L, sguid); | ||
return 1; | ||
} | ||
|
||
inline int guid_tohex(lua_State* L, uint64_t guid) { | ||
char sguid[32]; | ||
snprintf(sguid, 32, "%016lx", guid); | ||
lua_pushstring(L, sguid); | ||
return 1; | ||
} | ||
|
||
inline uint64_t guid_number(std::string guid) { | ||
return strtoull(guid.c_str(), nullptr, 10); | ||
} | ||
|
||
inline int guid_encode(lua_State* L) { | ||
char tmp[LETTER_LEN]; | ||
memset(tmp, 0, LETTER_LEN); | ||
uint64_t val = (lua_gettop(L) > 0) ? lua_tointeger(L, 1) : guid_new(0, 0); | ||
for (int i = 0; i < LETTER_LEN - 1; ++i) { | ||
tmp[i] = letter[val % LETTER_SIZE]; | ||
val /= LETTER_SIZE; | ||
if (val == 0) break; | ||
} | ||
lua_pushstring(L, tmp); | ||
return 1; | ||
} | ||
|
||
inline int find_index(char val) { | ||
if (val >= 97) return val - 61; | ||
if (val >= 65) return val - 55; | ||
return val - 48; | ||
} | ||
|
||
inline uint64_t guid_decode(std::string sval){ | ||
uint64_t val = 0; | ||
size_t len = sval.size(); | ||
const char* cval = sval.c_str(); | ||
for (int i = 0; i < len; ++i) { | ||
val += uint64_t(find_index(cval[i]) * pow(LETTER_SIZE, i)); | ||
} | ||
return val; | ||
} | ||
|
||
inline size_t format_guid(lua_State* L) { | ||
if (lua_type(L, 1) == LUA_TSTRING) { | ||
char* chEnd = NULL; | ||
const char* sguid = lua_tostring(L, 1); | ||
return strtoull(sguid, &chEnd, 16); | ||
} | ||
else { | ||
return lua_tointeger(L, 1); | ||
} | ||
} | ||
|
||
inline int guid_group(lua_State* L) { | ||
size_t guid = format_guid(L); | ||
lua_pushinteger(L, guid & 0x7f); | ||
return 1; | ||
} | ||
|
||
inline int guid_index(lua_State* L) { | ||
size_t guid = format_guid(L); | ||
lua_pushinteger(L, (guid >> GROUP_BITS) & 0xfff); | ||
return 1; | ||
} | ||
|
||
inline int guid_time(lua_State* L) { | ||
size_t guid = format_guid(L); | ||
size_t time = (guid >> (GROUP_BITS + INDEX_BITS + SNUM_BITS)) & 0x3fffffff; | ||
lua_pushinteger(L, time + BASE_TIME); | ||
return 1; | ||
} | ||
|
||
inline int guid_source(lua_State* L) { | ||
size_t guid = format_guid(L); | ||
lua_pushinteger(L, guid & 0x7f); | ||
lua_pushinteger(L, (guid >> GROUP_BITS) & 0xfff); | ||
lua_pushinteger(L, ((guid >> (GROUP_BITS + INDEX_BITS + SNUM_BITS)) & 0x3fffffff) + BASE_TIME); | ||
return 3; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#pragma once | ||
|
||
namespace luakit { | ||
|
||
inline int hash_code(lua_State* L) { | ||
size_t hcode = 0; | ||
int type = lua_type(L, 1); | ||
if (type == LUA_TNUMBER) { | ||
hcode = std::hash<int64_t>{}(lua_tointeger(L, 1)); | ||
} else if (type == LUA_TSTRING) { | ||
hcode = std::hash<std::string>{}(lua_tostring(L, 1)); | ||
} else { | ||
luaL_error(L, "hashkey only support number or string!"); | ||
} | ||
size_t mod = luaL_optinteger(L, 2, 0); | ||
if (mod > 0) { | ||
hcode = (hcode % mod) + 1; | ||
} | ||
lua_pushinteger(L, hcode); | ||
return 1; | ||
} | ||
|
||
inline uint32_t fnv_1_32(const char* bp, uint32_t hval) { | ||
unsigned char* be = (unsigned char*)bp; | ||
while (*bp) { | ||
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); | ||
hval ^= (uint32_t)*bp++; | ||
} | ||
return hval; | ||
} | ||
|
||
inline int fnv_1_32_l(lua_State* L) { | ||
size_t len; | ||
const char* bp = lua_tolstring(L, 1, &len); | ||
uint32_t hval = luaL_optinteger(L, 2, 0); | ||
lua_pushinteger(L, fnv_1_32(bp, hval)); | ||
return 1; | ||
} | ||
|
||
inline uint32_t fnv_1a_32(const char* b, size_t len, uint32_t hval) { | ||
unsigned char* bp = (unsigned char*)b; | ||
unsigned char* be = bp + len; | ||
while (bp < be) { | ||
hval ^= (uint32_t)*bp++; | ||
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); | ||
} | ||
return hval; | ||
} | ||
|
||
inline int fnv_1a_32_l(lua_State* L) { | ||
size_t len; | ||
const char* bp = lua_tolstring(L, 1, &len); | ||
uint32_t hval = luaL_optinteger(L, 2, 0); | ||
lua_pushinteger(L, fnv_1a_32(bp, len, hval)); | ||
return 1; | ||
} | ||
|
||
const uint32_t c1 = 0xcc9e2d51; | ||
const uint32_t c2 = 0x1b873593; | ||
inline uint32_t rotl32(uint32_t x, int8_t r) { | ||
return (x << r) | (x >> (32 - r)); | ||
} | ||
|
||
inline uint32_t murmur3_32(const uint8_t* data, size_t length) { | ||
uint32_t h1 = 0; | ||
const int nblocks = length / 4; | ||
// body | ||
const uint32_t* blocks = (const uint32_t *)(data + nblocks*4); | ||
for(int i = -nblocks; i; i++) { | ||
uint32_t k1 = blocks[i]; | ||
k1 *= c1; | ||
k1 = rotl32(k1, 15); | ||
k1 *= c2; | ||
h1 ^= k1; | ||
h1 = rotl32(h1, 13); | ||
h1 = h1*5 + 0xe6546b64; | ||
} | ||
// tail | ||
const uint8_t * tail = (const uint8_t*)(data + nblocks*4); | ||
uint32_t k1 = 0; | ||
switch(length & 3) | ||
{ | ||
case 3: k1 ^= tail[2] << 16; | ||
case 2: k1 ^= tail[1] << 8; | ||
case 1: k1 ^= tail[0]; | ||
k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1; | ||
}; | ||
// finalization | ||
h1 ^= length; | ||
//fmix32 | ||
h1 ^= h1 >> 16; | ||
h1 *= 0x85ebca6b; | ||
h1 ^= h1 >> 13; | ||
h1 *= 0xc2b2ae35; | ||
h1 ^= h1 >> 16; | ||
return h1; | ||
} | ||
|
||
inline int murmur3_32_l(lua_State* L) { | ||
size_t length; | ||
const uint8_t * data = (const uint8_t*)lua_tolstring(L, 1, &length); | ||
lua_pushinteger(L, murmur3_32(data, length)); | ||
return 1; | ||
} | ||
|
||
inline int32_t jumphash(uint64_t key, int32_t num_buckets) { | ||
int64_t b = -1, j = 0; | ||
while (j < num_buckets) { | ||
b = j; | ||
key = key * 2862933555777941757ULL + 1; | ||
j = (b + 1) * (double(1LL << 31) / double((key >> 33) + 1)); | ||
} | ||
return b; | ||
} | ||
|
||
inline int jumphash_l(lua_State* L) { | ||
uint64_t key = 0; | ||
int type = lua_type(L, 1); | ||
if (type == LUA_TNUMBER) { | ||
key = lua_tointeger(L, 1); | ||
} else if (type == LUA_TSTRING) { | ||
key = fnv_1_32(lua_tostring(L, 1), 0); | ||
} else { | ||
luaL_error(L, "hashkey only support number or string!"); | ||
} | ||
int32_t num_buckets = lua_tointeger(L, 2); | ||
int32_t hval = jumphash(key, num_buckets); | ||
lua_pushinteger(L, hval + 1); | ||
return 1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters