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.
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