1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
/*
* Copyright 2025 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "lua_common.h"
#include "lua_classnames.h"
#include "shingles.h"
#include "contrib/fmt/include/fmt/format.h"
/***
* @module rspamd_shingle
* This module provides methods to work with text shingles
*/
/***
* @method shingle:to_table()
* Converts shingle to table of decimal strings
* @return {table} table of RSPAMD_SHINGLE_SIZE decimal strings
*/
LUA_FUNCTION_DEF(shingle, to_table);
/***
* @method shingle:get(index)
* Gets element at index as two lua_Integer values (high and low 32 bits)
* @param {number} index 1-based index
* @return {number,number} high and low 32-bit parts
*/
LUA_FUNCTION_DEF(shingle, get);
/***
* @method shingle:get_string(index)
* Gets element at index as decimal string
* @param {number} index 1-based index
* @return {string} decimal representation
*/
LUA_FUNCTION_DEF(shingle, get_string);
static const struct luaL_reg shinglelib_m[] = {
LUA_INTERFACE_DEF(shingle, to_table),
LUA_INTERFACE_DEF(shingle, get),
LUA_INTERFACE_DEF(shingle, get_string),
{"__tostring", rspamd_lua_class_tostring},
{nullptr, nullptr}};
static struct rspamd_shingle *
lua_check_shingle(lua_State *L, int pos)
{
void *ud = rspamd_lua_check_udata(L, pos, rspamd_shingle_classname);
luaL_argcheck(L, ud != nullptr, pos, "'shingle' expected");
return static_cast<struct rspamd_shingle *>(ud);
}
void lua_newshingle(lua_State *L, const void *sh)
{
auto *nsh = static_cast<struct rspamd_shingle *>(
lua_newuserdata(L, sizeof(struct rspamd_shingle)));
if (sh != nullptr) {
memcpy(nsh, sh, sizeof(struct rspamd_shingle));
}
rspamd_lua_setclass(L, rspamd_shingle_classname, -1);
}
static int
lua_shingle_to_table(lua_State *L)
{
LUA_TRACE_POINT;
auto *sh = lua_check_shingle(L, 1);
lua_createtable(L, RSPAMD_SHINGLE_SIZE, 0);
for (int i = 0; i < RSPAMD_SHINGLE_SIZE; i++) {
auto str = fmt::format("{}", sh->hashes[i]);
lua_pushstring(L, str.c_str());
lua_rawseti(L, -2, i + 1);
}
return 1;
}
static int
lua_shingle_get(lua_State *L)
{
LUA_TRACE_POINT;
auto *sh = lua_check_shingle(L, 1);
auto idx = luaL_checkinteger(L, 2) - 1;
if (idx < 0 || idx >= RSPAMD_SHINGLE_SIZE) {
return luaL_error(L, "index out of bounds: %d", idx + 1);
}
uint64_t val = sh->hashes[idx];
lua_pushinteger(L, (lua_Integer) (val >> 32));
lua_pushinteger(L, (lua_Integer) (val & 0xFFFFFFFF));
return 2;
}
static int
lua_shingle_get_string(lua_State *L)
{
LUA_TRACE_POINT;
auto *sh = lua_check_shingle(L, 1);
auto idx = luaL_checkinteger(L, 2) - 1;
if (idx < 0 || idx >= RSPAMD_SHINGLE_SIZE) {
return luaL_error(L, "index out of bounds: %d", idx + 1);
}
auto str = fmt::format("{}", sh->hashes[idx]);
lua_pushstring(L, str.c_str());
return 1;
}
void luaopen_shingle(lua_State *L)
{
rspamd_lua_new_class(L, rspamd_shingle_classname, shinglelib_m);
lua_pop(L, 1);
}
|