hsss 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|