hsss 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +91 -12
- data/exe/hsss +14 -4
- data/lib/hsss/version.rb +1 -1
- data/lib/hsss.rb +116 -35
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cab7c750dbb0557910fd637a4a29df79cb40db04
|
4
|
+
data.tar.gz: 5286db254bacd9b9288795d52a1c842992ac7b59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24693aa14136f137c4d20f6472ce88200c288d677260ea25aead6eff9055449ea42de5de0ae4334bce38d90027169275947e0837ce59c8ee659c30bc5f8ef32d
|
7
|
+
data.tar.gz: c2700387cb67d163119f1d081a38ebd2ee8969f550665bed4e012f73e5b19b9a939f7fffbf396350fbfc6912416b8ce900e5b655900381887ae7f74b85bef233
|
data/README.md
CHANGED
@@ -4,16 +4,24 @@ Hash-Safe Script Splinterer, a Lua Script and hash embedder into C source.
|
|
4
4
|
Good for putting Redis Lua scripts in your C headers.
|
5
5
|
```
|
6
6
|
Usage: hsss [options] files
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
--format [whole|split] Output as separate or a single struct
|
8
|
+
--struct [redis_lua_scripts_t]
|
9
|
+
C struct name
|
10
|
+
--row-struct [redis_lua_script_t]
|
11
|
+
Hash+name+script struct for 'whole' format.
|
12
|
+
--scripts [redis_lua_scripts]
|
13
|
+
Scripts variable (split or whole format)
|
14
|
+
--hashes [redis_lua_hashes] Hashes variable (split format)
|
15
|
+
--names [redis_lua_script_names]
|
16
|
+
Script names variable (split format)
|
17
|
+
--count [redis_lua_scripts_count]
|
18
|
+
integer script count variable
|
19
|
+
--no-count Omit script count variable
|
20
|
+
--each-macro [REDIS_LUA_SCRIPTS_EACH]
|
21
|
+
Iterator macro
|
22
|
+
--no-each Omit the iterator macro
|
23
|
+
--no-parse Skip using luac to check script syntax
|
24
|
+
--prefix PREFIX Prefix default names with this
|
17
25
|
```
|
18
26
|
|
19
27
|
## Example
|
@@ -34,7 +42,43 @@ redis.call('del', KEYS[1])
|
|
34
42
|
|
35
43
|
```
|
36
44
|
|
37
|
-
|
45
|
+
|
46
|
+
running `hsss example/*.lua` ("whole" format produces
|
47
|
+
```c
|
48
|
+
// don't edit this please, it was auto-generated by hsss
|
49
|
+
// https://github.com/slact/hsss
|
50
|
+
|
51
|
+
typedef struct {
|
52
|
+
char *name;
|
53
|
+
char *hash;
|
54
|
+
char *script;
|
55
|
+
} redis_lua_script_t;
|
56
|
+
|
57
|
+
typedef struct {
|
58
|
+
//deletes first key
|
59
|
+
redis_lua_script_t delete;
|
60
|
+
|
61
|
+
//echoes the first argument
|
62
|
+
redis_lua_script_t echo;
|
63
|
+
|
64
|
+
} redis_lua_scripts_t;
|
65
|
+
|
66
|
+
static redis_lua_scripts_t redis_lua_scripts = {
|
67
|
+
{"delete", "c6929c34f10b0fe8eaba42cde275652f32904e03",
|
68
|
+
"--deletes first key\n"
|
69
|
+
"redis.call('del', KEYS[1])\n"},
|
70
|
+
|
71
|
+
{"echo", "8f8f934c6049ab4d6337cfa53976893417b268bc",
|
72
|
+
"--echoes the first argument\n"
|
73
|
+
"redis.call('echo', ARGS[1])\n"}
|
74
|
+
};
|
75
|
+
|
76
|
+
const int redis_lua_scripts_count=2;
|
77
|
+
#define REDIS_LUA_SCRIPTS_EACH(script) \
|
78
|
+
for((script)=(redis_lua_script_t *)&redis_lua_scripts; (script) < (redis_lua_script_t *)(&redis_lua_scripts + 1); (script)++)
|
79
|
+
```
|
80
|
+
|
81
|
+
running `hsss --format split example/*.lua` outputs
|
38
82
|
```c
|
39
83
|
// don't edit this please, it was auto-generated by hsss
|
40
84
|
// https://github.com/slact/hsss
|
@@ -75,13 +119,19 @@ for((script_src)=(char **)&redis_lua_scripts, (script_hash)=(char **)&redis_lua_
|
|
75
119
|
|
76
120
|
## Using in your C code
|
77
121
|
|
78
|
-
- `EVALSHA`:
|
122
|
+
- `EVALSHA`:
|
123
|
+
|
79
124
|
```c
|
125
|
+
//whole format
|
126
|
+
redisAsyncCommand(asyncContext, callback, data, "EVALSHA %s 0", redis_lua_scripts.script_name.hash);
|
127
|
+
|
128
|
+
//split format
|
80
129
|
redisAsyncCommand(asyncContext, callback, data, "EVALSHA %s 0", redis_lua_hashes.script_name);
|
81
130
|
```
|
82
131
|
|
83
132
|
- iterator macro, loading scripts
|
84
133
|
```c
|
134
|
+
//split format:
|
85
135
|
|
86
136
|
//privdata for error checking callback
|
87
137
|
typedef struct {
|
@@ -118,6 +168,35 @@ for((script_src)=(char **)&redis_lua_scripts, (script_hash)=(char **)&redis_lua_
|
|
118
168
|
}
|
119
169
|
```
|
120
170
|
|
171
|
+
```c
|
172
|
+
//whole format:
|
173
|
+
|
174
|
+
//error checking callback
|
175
|
+
static void redisLoadScriptCallback(redisAsyncContext *c, void *r, void *privdata) {
|
176
|
+
redis_lua_script_t *script = privdata;
|
177
|
+
redisReply *reply = r;
|
178
|
+
if (reply == NULL) return;
|
179
|
+
switch(reply->type) {
|
180
|
+
case REDIS_REPLY_ERROR:
|
181
|
+
printf("Failed loading redis lua script %s :%s", script->name, reply->str);
|
182
|
+
break;
|
183
|
+
case REDIS_REPLY_STRING:
|
184
|
+
if(nstrncmp(reply->str, script->hash, 40)!=0) {
|
185
|
+
printf("Redis lua script %s has unexpected hash %s (expected %s)", script->name, reply->str, script->hash);
|
186
|
+
}
|
187
|
+
break;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
static void redisInitScripts(redisAsyncContext *c){
|
192
|
+
redis_lua_script_t *script;
|
193
|
+
|
194
|
+
REDIS_LUA_SCRIPTS_EACH(script) {
|
195
|
+
redisAsyncCommand(c, redisLoadScriptCallback, script, "SCRIPT LOAD %s", script->script);
|
196
|
+
}
|
197
|
+
}
|
198
|
+
```
|
199
|
+
|
121
200
|
## License
|
122
201
|
|
123
202
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/exe/hsss
CHANGED
@@ -4,10 +4,12 @@ require "optparse"
|
|
4
4
|
opt={}
|
5
5
|
|
6
6
|
arg=OptionParser.new do |opts|
|
7
|
+
opts.on("--format [split|whole]", "Output as separate or a single struct"){|v| opt[:format]= v}
|
7
8
|
opts.on("--struct [#{Hsss::DEFAULT_STRUCT_NAME}]", "C struct name"){|v| opt[:struct_name]= v}
|
8
|
-
opts.on("--
|
9
|
-
opts.on("--
|
10
|
-
opts.on("--
|
9
|
+
opts.on("--row-struct [#{Hsss::DEFAULT_ROW_STRUCT_NAME}]", "Hash+name+script struct for 'whole' format."){|v| opt[:row_struct_name]= v}
|
10
|
+
opts.on("--scripts [#{Hsss::DEFAULT_SCRIPTS_NAME}]", "Scripts variable (split or whole format)"){|v| opt[:scripts_struct]=v}
|
11
|
+
opts.on("--hashes [#{Hsss::DEFAULT_HASHES_NAME}]", "Hashes variable (split format)"){|v| opt[:hashes_struct]=v}
|
12
|
+
opts.on("--names [#{Hsss::DEFAULT_NAMES_NAME}]", "Script names variable (split format)"){|v| opt[:names_struct]=v}
|
11
13
|
opts.on("--count [#{Hsss::DEFAULT_COUNT_NAME}]", "integer script count variable"){|v| opt[:count_name]=v}
|
12
14
|
opts.on("--no-count", "Omit script count variable"){opt[:skip_count]=true}
|
13
15
|
opts.on("--each-macro [#{Hsss::DEFAULT_ITER_MACRO_NAME}]", "Iterator macro"){|v| opt[:iter_macro_name]=v}
|
@@ -24,7 +26,15 @@ arg.version=Hsss::VERSION
|
|
24
26
|
|
25
27
|
rest = arg.parse!
|
26
28
|
|
27
|
-
|
29
|
+
case opt[:format]
|
30
|
+
when nil, "split"
|
31
|
+
hsss = Hsss::CSplit.new(rest, opt)
|
32
|
+
when "whole"
|
33
|
+
hsss = Hsss::CWhole.new(rest, opt)
|
34
|
+
else
|
35
|
+
STDERR.puts "Invalid format #{opt[:format]}."
|
36
|
+
exit 1
|
37
|
+
end
|
28
38
|
|
29
39
|
exit 1 if hsss.failed?
|
30
40
|
|
data/lib/hsss/version.rb
CHANGED
data/lib/hsss.rb
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
require "hsss/version"
|
2
2
|
require 'digest/sha1'
|
3
|
-
|
3
|
+
require "pry"
|
4
4
|
module Hsss
|
5
|
-
DEFAULT_STRUCT_NAME="
|
5
|
+
DEFAULT_STRUCT_NAME="redis_lua_scripts_t"
|
6
|
+
DEFAULT_ROW_STRUCT_NAME="redis_lua_script_t"
|
6
7
|
DEFAULT_HASHES_NAME="redis_lua_hashes"
|
7
8
|
DEFAULT_NAMES_NAME="redis_lua_script_names"
|
8
9
|
DEFAULT_SCRIPTS_NAME="redis_lua_scripts"
|
9
10
|
DEFAULT_COUNT_NAME="redis_lua_scripts_count"
|
10
11
|
DEFAULT_ITER_MACRO_NAME="REDIS_LUA_SCRIPTS_EACH"
|
11
12
|
|
12
|
-
class
|
13
|
+
class COutput
|
13
14
|
EXT="lua"
|
15
|
+
attr_accessor :struct_name, :hashes_struct, :names_struct, :scripts_struct, :count_name, :iter_macro_name, :row_struct_name
|
14
16
|
|
15
|
-
attr_accessor :struct_name, :hashes_struct, :names_struct, :scripts_struct, :count_name, :iter_macro_name
|
16
17
|
def initialize(files, opt={})
|
17
18
|
@scripts={}
|
18
|
-
|
19
19
|
{ struct_name: DEFAULT_STRUCT_NAME,
|
20
|
+
row_struct_name: DEFAULT_ROW_STRUCT_NAME,
|
20
21
|
hashes_struct: DEFAULT_HASHES_NAME,
|
21
22
|
names_struct: DEFAULT_NAMES_NAME,
|
22
23
|
scripts_struct: DEFAULT_SCRIPTS_NAME,
|
@@ -45,28 +46,6 @@ module Hsss
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
@cout= <<-EOS.gsub(/^ {8}/, '')
|
49
|
-
// don't edit this please, it was auto-generated by hsss
|
50
|
-
// https://github.com/slact/hsss
|
51
|
-
|
52
|
-
typedef struct {
|
53
|
-
%s
|
54
|
-
} #{struct_name};
|
55
|
-
|
56
|
-
static #{struct_name} #{hashes_struct} = {
|
57
|
-
%s
|
58
|
-
};
|
59
|
-
|
60
|
-
static #{struct_name} #{names_struct} = {
|
61
|
-
%s
|
62
|
-
};
|
63
|
-
|
64
|
-
static #{struct_name} #{scripts_struct} = {
|
65
|
-
%s
|
66
|
-
};
|
67
|
-
|
68
|
-
EOS
|
69
|
-
|
70
49
|
@struct=[]
|
71
50
|
@name_table=[]
|
72
51
|
@script_table=[]
|
@@ -76,7 +55,7 @@ module Hsss
|
|
76
55
|
name=v.first
|
77
56
|
script=v.last
|
78
57
|
|
79
|
-
@name_table <<
|
58
|
+
@name_table << name
|
80
59
|
|
81
60
|
str=[]
|
82
61
|
for l in script.lines do
|
@@ -84,14 +63,13 @@ module Hsss
|
|
84
63
|
break unless cmt
|
85
64
|
str << " //#{cmt[1]}"
|
86
65
|
end
|
87
|
-
str << "
|
66
|
+
str << " #{script_name_line(name)}\n"
|
88
67
|
@struct << str.join("\n")
|
89
68
|
|
90
|
-
@script_table <<
|
69
|
+
@script_table << script_string(name, script)
|
91
70
|
|
92
|
-
@hashed_table <<
|
71
|
+
@hashed_table << Digest::SHA1.hexdigest(script)
|
93
72
|
end
|
94
|
-
|
95
73
|
end
|
96
74
|
|
97
75
|
def check_script(path)
|
@@ -100,20 +78,60 @@ module Hsss
|
|
100
78
|
ret
|
101
79
|
end
|
102
80
|
|
103
|
-
def cquote(str)
|
81
|
+
def cquote(str, line_start="")
|
104
82
|
out=[]
|
105
83
|
str.each_line do |l|
|
106
84
|
l.sub! "\n", "\\n"
|
107
85
|
l.gsub! '"', '\"'
|
108
|
-
l.gsub! /^(.*)$/, "
|
86
|
+
l.gsub! /^(.*)$/, "#{line_start}\"\\1\""
|
109
87
|
out << l
|
110
88
|
end
|
111
89
|
out.join "\n"
|
112
90
|
end
|
113
91
|
|
92
|
+
def failed?
|
93
|
+
@failed
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class CSplit < COutput
|
98
|
+
|
99
|
+
def initialize(files, opt={})
|
100
|
+
super
|
101
|
+
@cout= <<-EOS.gsub(/^ {8}/, '')
|
102
|
+
// don't edit this please, it was auto-generated by hsss
|
103
|
+
// https://github.com/slact/hsss
|
104
|
+
|
105
|
+
typedef struct {
|
106
|
+
%s
|
107
|
+
} #{struct_name};
|
108
|
+
|
109
|
+
static #{struct_name} #{hashes_struct} = {
|
110
|
+
%s
|
111
|
+
};
|
112
|
+
|
113
|
+
static #{struct_name} #{names_struct} = {
|
114
|
+
%s
|
115
|
+
};
|
116
|
+
|
117
|
+
static #{struct_name} #{scripts_struct} = {
|
118
|
+
%s
|
119
|
+
};
|
120
|
+
|
121
|
+
EOS
|
122
|
+
end
|
123
|
+
|
124
|
+
def script_name_line(name)
|
125
|
+
"char *#{name};"
|
126
|
+
end
|
127
|
+
|
128
|
+
def script_string(name, script)
|
129
|
+
" //#{name}\n#{cquote(script, " ")}"
|
130
|
+
end
|
131
|
+
|
114
132
|
def to_s
|
115
133
|
if @scripts.count > 0
|
116
|
-
out=sprintf @cout, @struct.join("\n"), @hashed_table.join(",\n"), @name_table.join("\n"), @script_table.join(",\n\n")
|
134
|
+
out=sprintf @cout, @struct.join("\n"), @hashed_table.map{|v|" \"#{v}\""}.join(",\n"), @name_table.map{|v|" \"#{v}\","}.join("\n"), @script_table.join(",\n\n")
|
117
135
|
else
|
118
136
|
out="//nothing here\n"
|
119
137
|
end
|
@@ -130,8 +148,71 @@ module Hsss
|
|
130
148
|
out
|
131
149
|
end
|
132
150
|
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
class CWhole < COutput
|
157
|
+
EXT="lua"
|
158
|
+
|
159
|
+
def initialize(files, opt={})
|
160
|
+
super
|
161
|
+
@cout= <<-EOS.gsub(/^ {8}/, '')
|
162
|
+
// don't edit this please, it was auto-generated by hsss
|
163
|
+
// https://github.com/slact/hsss
|
164
|
+
|
165
|
+
typedef struct {
|
166
|
+
char *name;
|
167
|
+
char *hash;
|
168
|
+
char *script;
|
169
|
+
} #{row_struct_name};
|
170
|
+
|
171
|
+
typedef struct {
|
172
|
+
%s
|
173
|
+
} #{struct_name};
|
174
|
+
|
175
|
+
static #{struct_name} #{scripts_struct} = {
|
176
|
+
%s
|
177
|
+
};
|
178
|
+
|
179
|
+
EOS
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
def script_name_line(name)
|
184
|
+
"#{row_struct_name} #{name};"
|
185
|
+
end
|
186
|
+
def script_string(name, script)
|
187
|
+
cquote(script, " ")
|
188
|
+
end
|
189
|
+
def to_s
|
190
|
+
if @scripts.count > 0
|
191
|
+
scrapts=[]
|
192
|
+
for i in 0...@scripts.count do
|
193
|
+
scrapts<< " {\"#{@name_table[i]}\", \"#{@hashed_table[i]}\",\n#{@script_table[i]}}"
|
194
|
+
end
|
195
|
+
out=sprintf @cout, @struct.join("\n"), scrapts.join(",\n\n")
|
196
|
+
else
|
197
|
+
out="//nothing here\n"
|
198
|
+
end
|
199
|
+
|
200
|
+
out << "const int #{@count_name}=#{@scripts.count};\n" if @include_count
|
201
|
+
|
202
|
+
if @include_iter_macro
|
203
|
+
macro = []
|
204
|
+
macro << "#define #{iter_macro_name}(script) \\"
|
205
|
+
macro << "for((script)=(#{row_struct_name} *)&#{scripts_struct}; (script) < (#{row_struct_name} *)(&#{scripts_struct} + 1); (script)++) "
|
206
|
+
out << macro.join("\n")
|
207
|
+
end
|
208
|
+
|
209
|
+
out
|
210
|
+
end
|
211
|
+
|
133
212
|
def failed?
|
134
213
|
@failed
|
135
214
|
end
|
136
215
|
end
|
216
|
+
|
217
|
+
|
137
218
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hsss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leo P.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|