hsss 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +91 -12
  3. data/exe/hsss +14 -4
  4. data/lib/hsss/version.rb +1 -1
  5. data/lib/hsss.rb +116 -35
  6. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 487fa212d82812cc8a4857fa40ac9c187f24655f
4
- data.tar.gz: adcd2bfd44090494e15c4c5e1244136cfe1597a4
3
+ metadata.gz: cab7c750dbb0557910fd637a4a29df79cb40db04
4
+ data.tar.gz: 5286db254bacd9b9288795d52a1c842992ac7b59
5
5
  SHA512:
6
- metadata.gz: 05afc51d04680fbfe69190cde89918e5838156858c25ce88c6a9001d4eab710808ae623d8d9535283a5c148f446e33ba117a7ea131bd3cfbfebf1a62d3ebfa6b
7
- data.tar.gz: 0d1d0db05ab197ab623540b023ed7a5777886a4bb04c6c55b8c411d6fd930a56c0ce5e6cefed2c6a5de470d182354764e80bee64c7f6107c92970a4d33729c7d
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
- --struct [redis_lua_script_t] C struct name
8
- --scripts [redis_lua_scripts] Scripts variable
9
- --hashes [redis_lua_hashes] Hashes variable
10
- --names [redis_lua_script_names] Script names variable
11
- --count [redis_lua_scripts_count] integer script count variable
12
- --no-count Omit script count variable
13
- --each-macro [REDIS_LUA_SCRIPTS_EACH] Iterator macro
14
- --no-each Omit the iterator macro
15
- --no-parse Skip using luac to check script syntax
16
- --prefix PREFIX Prefix default names with this
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
- running `hsss example/*.lua` outputs
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("--scripts [#{Hsss::DEFAULT_SCRIPTS_NAME}]", "Scripts variable"){|v| opt[:scripts_struct]=v}
9
- opts.on("--hashes [#{Hsss::DEFAULT_HASHES_NAME}]", "Hashes variable"){|v| opt[:hashes_struct]=v}
10
- opts.on("--names [#{Hsss::DEFAULT_NAMES_NAME}]", "Script names variable"){|v| opt[:names_struct]=v}
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
- hsss = Hsss::Hsss.new(rest, opt)
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
@@ -1,3 +1,3 @@
1
1
  module Hsss
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
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="redis_lua_script_t"
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 Hsss
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 << " \"#{name}\","
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 << " char *#{name};\n"
66
+ str << " #{script_name_line(name)}\n"
88
67
  @struct << str.join("\n")
89
68
 
90
- @script_table << " //#{name}\n#{cquote(script)}"
69
+ @script_table << script_string(name, script)
91
70
 
92
- @hashed_table << " \"#{Digest::SHA1.hexdigest script}\""
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! /^(.*)$/, " \"\\1\""
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.6
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-18 00:00:00.000000000 Z
11
+ date: 2016-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler