inih 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ddb0233107d7ad4ce1121c75fd29a94de7d5dc42
4
+ data.tar.gz: 42fc11b4b2f16e971e61c189b45ecf652ae71ffb
5
+ SHA512:
6
+ metadata.gz: 4727253857a6bdc0472b47792631ded48e2a125bfc0acfeb649b19f7869d92e4f02dded4f215e32d9dd8a307ecd29bd5c83c211ec6c404cc902f59afb7c00824
7
+ data.tar.gz: fcd4cd91b83fb9316a0366818c653e5f3c867f144ebb6c34761a7b904751c32f85251861c4f9f5e280affcdc523e76a6f06aebc053c15e9c4f9cde59ec906dfb
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --no-private --markup-provider=redcarpet --markup=markdown - README.md LICENSE ext/inih/LICENSE
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 William Woodruff <william @ yossarian.net>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ ruby-inih
2
+ =========
3
+
4
+ A Ruby wrapper for [inih](https://github.com/benhoyt/inih), a simple INI parser.
5
+
6
+ ### Installation
7
+
8
+ ```ruby
9
+ $ gem install inih
10
+ ```
11
+
12
+ ### Example
13
+
14
+ Given the following INI data:
15
+
16
+ ```ini
17
+ ; example.ini
18
+ [example]
19
+ foo=bar
20
+ baz = quux
21
+ integer = 10
22
+ float = 3.14
23
+ bool = true
24
+ ```
25
+
26
+ ```ruby
27
+ # load directly from a file
28
+ INIH.load "example.ini"
29
+ # => {"example"=>{"foo"=>"bar", "baz"=>"quux", "integer"=>10, "float"=>3.14, "bool"=>true}}
30
+
31
+ # parse from a string
32
+ INIH.parse "[section]\nkey=value"
33
+ #=> {"section"=>{"key"=>"value"}}
34
+ ```
35
+
36
+ Integers, floating-point numbers, and booleans are coerced into their respective Ruby types.
37
+
38
+ ### TODO
39
+
40
+ * Unit tests
41
+ * Coerce scientific-notation?
42
+
43
+ ### License
44
+
45
+ inih itself is licensed under the BSD License.
46
+
47
+ For the exact terms, see the [LICENSE](ext/inih/LICENSE) file.
48
+
49
+ ruby-inih is licensed under the MIT License.
50
+
51
+ For the exact terms, see the [LICENSE](./LICENSE) file.
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+
5
+ $CFLAGS << " -DINI_MAX_LINE=1024 "
6
+
7
+ create_makefile "ext/inih"
data/ext/inih/ini.c ADDED
@@ -0,0 +1,244 @@
1
+ /* inih -- simple .INI file parser
2
+
3
+ inih is released under the New BSD license (see LICENSE.txt). Go to the project
4
+ home page for more info:
5
+
6
+ https://github.com/benhoyt/inih
7
+
8
+ */
9
+
10
+ #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
11
+ #define _CRT_SECURE_NO_WARNINGS
12
+ #endif
13
+
14
+ #include <stdio.h>
15
+ #include <ctype.h>
16
+ #include <string.h>
17
+
18
+ #include "ini.h"
19
+
20
+ #if !INI_USE_STACK
21
+ #include <stdlib.h>
22
+ #endif
23
+
24
+ #define MAX_SECTION 50
25
+ #define MAX_NAME 50
26
+
27
+ /* Used by ini_parse_string() to keep track of string parsing state. */
28
+ typedef struct {
29
+ const char* ptr;
30
+ size_t num_left;
31
+ } ini_parse_string_ctx;
32
+
33
+ /* Strip whitespace chars off end of given string, in place. Return s. */
34
+ static char* rstrip(char* s)
35
+ {
36
+ char* p = s + strlen(s);
37
+ while (p > s && isspace((unsigned char)(*--p)))
38
+ *p = '\0';
39
+ return s;
40
+ }
41
+
42
+ /* Return pointer to first non-whitespace char in given string. */
43
+ static char* lskip(const char* s)
44
+ {
45
+ while (*s && isspace((unsigned char)(*s)))
46
+ s++;
47
+ return (char*)s;
48
+ }
49
+
50
+ /* Return pointer to first char (of chars) or inline comment in given string,
51
+ or pointer to null at end of string if neither found. Inline comment must
52
+ be prefixed by a whitespace character to register as a comment. */
53
+ static char* find_chars_or_comment(const char* s, const char* chars)
54
+ {
55
+ #if INI_ALLOW_INLINE_COMMENTS
56
+ int was_space = 0;
57
+ while (*s && (!chars || !strchr(chars, *s)) &&
58
+ !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
59
+ was_space = isspace((unsigned char)(*s));
60
+ s++;
61
+ }
62
+ #else
63
+ while (*s && (!chars || !strchr(chars, *s))) {
64
+ s++;
65
+ }
66
+ #endif
67
+ return (char*)s;
68
+ }
69
+
70
+ /* Version of strncpy that ensures dest (size bytes) is null-terminated. */
71
+ static char* strncpy0(char* dest, const char* src, size_t size)
72
+ {
73
+ strncpy(dest, src, size);
74
+ dest[size - 1] = '\0';
75
+ return dest;
76
+ }
77
+
78
+ /* See documentation in header file. */
79
+ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
80
+ void* user)
81
+ {
82
+ /* Uses a fair bit of stack (use heap instead if you need to) */
83
+ #if INI_USE_STACK
84
+ char line[INI_MAX_LINE];
85
+ #else
86
+ char* line;
87
+ #endif
88
+ char section[MAX_SECTION] = "";
89
+ char prev_name[MAX_NAME] = "";
90
+
91
+ char* start;
92
+ char* end;
93
+ char* name;
94
+ char* value;
95
+ int lineno = 0;
96
+ int error = 0;
97
+
98
+ #if !INI_USE_STACK
99
+ line = (char*)malloc(INI_MAX_LINE);
100
+ if (!line) {
101
+ return -2;
102
+ }
103
+ #endif
104
+
105
+ #if INI_HANDLER_LINENO
106
+ #define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
107
+ #else
108
+ #define HANDLER(u, s, n, v) handler(u, s, n, v)
109
+ #endif
110
+
111
+ /* Scan through stream line by line */
112
+ while (reader(line, INI_MAX_LINE, stream) != NULL) {
113
+ lineno++;
114
+
115
+ start = line;
116
+ #if INI_ALLOW_BOM
117
+ if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
118
+ (unsigned char)start[1] == 0xBB &&
119
+ (unsigned char)start[2] == 0xBF) {
120
+ start += 3;
121
+ }
122
+ #endif
123
+ start = lskip(rstrip(start));
124
+
125
+ if (*start == ';' || *start == '#') {
126
+ /* Per Python configparser, allow both ; and # comments at the
127
+ start of a line */
128
+ }
129
+ #if INI_ALLOW_MULTILINE
130
+ else if (*prev_name && *start && start > line) {
131
+ /* Non-blank line with leading whitespace, treat as continuation
132
+ of previous name's value (as per Python configparser). */
133
+ if (!HANDLER(user, section, prev_name, start) && !error)
134
+ error = lineno;
135
+ }
136
+ #endif
137
+ else if (*start == '[') {
138
+ /* A "[section]" line */
139
+ end = find_chars_or_comment(start + 1, "]");
140
+ if (*end == ']') {
141
+ *end = '\0';
142
+ strncpy0(section, start + 1, sizeof(section));
143
+ *prev_name = '\0';
144
+ }
145
+ else if (!error) {
146
+ /* No ']' found on section line */
147
+ error = lineno;
148
+ }
149
+ }
150
+ else if (*start) {
151
+ /* Not a comment, must be a name[=:]value pair */
152
+ end = find_chars_or_comment(start, "=:");
153
+ if (*end == '=' || *end == ':') {
154
+ *end = '\0';
155
+ name = rstrip(start);
156
+ value = end + 1;
157
+ #if INI_ALLOW_INLINE_COMMENTS
158
+ end = find_chars_or_comment(value, NULL);
159
+ if (*end)
160
+ *end = '\0';
161
+ #endif
162
+ value = lskip(value);
163
+ rstrip(value);
164
+
165
+ /* Valid name[=:]value pair found, call handler */
166
+ strncpy0(prev_name, name, sizeof(prev_name));
167
+ if (!HANDLER(user, section, name, value) && !error)
168
+ error = lineno;
169
+ }
170
+ else if (!error) {
171
+ /* No '=' or ':' found on name[=:]value line */
172
+ error = lineno;
173
+ }
174
+ }
175
+
176
+ #if INI_STOP_ON_FIRST_ERROR
177
+ if (error)
178
+ break;
179
+ #endif
180
+ }
181
+
182
+ #if !INI_USE_STACK
183
+ free(line);
184
+ #endif
185
+
186
+ return error;
187
+ }
188
+
189
+ /* See documentation in header file. */
190
+ int ini_parse_file(FILE* file, ini_handler handler, void* user)
191
+ {
192
+ return ini_parse_stream((ini_reader)fgets, file, handler, user);
193
+ }
194
+
195
+ /* See documentation in header file. */
196
+ int ini_parse(const char* filename, ini_handler handler, void* user)
197
+ {
198
+ FILE* file;
199
+ int error;
200
+
201
+ file = fopen(filename, "r");
202
+ if (!file)
203
+ return -1;
204
+ error = ini_parse_file(file, handler, user);
205
+ fclose(file);
206
+ return error;
207
+ }
208
+
209
+ /* An ini_reader function to read the next line from a string buffer. This
210
+ is the fgets() equivalent used by ini_parse_string(). */
211
+ static char* ini_reader_string(char* str, int num, void* stream) {
212
+ ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream;
213
+ const char* ctx_ptr = ctx->ptr;
214
+ size_t ctx_num_left = ctx->num_left;
215
+ char* strp = str;
216
+ char c;
217
+
218
+ if (ctx_num_left == 0 || num < 2)
219
+ return NULL;
220
+
221
+ while (num > 1 && ctx_num_left != 0) {
222
+ c = *ctx_ptr++;
223
+ ctx_num_left--;
224
+ *strp++ = c;
225
+ if (c == '\n')
226
+ break;
227
+ num--;
228
+ }
229
+
230
+ *strp = '\0';
231
+ ctx->ptr = ctx_ptr;
232
+ ctx->num_left = ctx_num_left;
233
+ return str;
234
+ }
235
+
236
+ /* See documentation in header file. */
237
+ int ini_parse_string(const char* string, ini_handler handler, void* user) {
238
+ ini_parse_string_ctx ctx;
239
+
240
+ ctx.ptr = string;
241
+ ctx.num_left = strlen(string);
242
+ return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
243
+ user);
244
+ }
data/ext/inih/inih.c ADDED
@@ -0,0 +1,79 @@
1
+ #include "inih.h"
2
+
3
+ VALUE mINIH = Qnil;
4
+
5
+ static int mINIH_ini_handler(void *data, const char *sect, const char *name, const char *val);
6
+
7
+ /*
8
+ @overload parse(string)
9
+ Parse an INI-formatted string into a Hash.
10
+ @param string [String] the INI-formatted string to parse
11
+ @return [Hash] the resulting hash
12
+ @raise [RuntimeError] if a parse error occurs
13
+ */
14
+ static VALUE mINIH_parse(VALUE self, VALUE string);
15
+
16
+ /*
17
+ @overload load(filename)
18
+ Parse an INI-formatted file into a Hash.
19
+ @param filename [String] the INI-formatted file to parse
20
+ @return [Hash] the resulting hash
21
+ @raise [RuntimeError] if a parse or I/O error occurs
22
+ */
23
+ static VALUE mINIH_load(VALUE self, VALUE filename);
24
+
25
+ void Init_inih()
26
+ {
27
+ mINIH = rb_define_module("INIH");
28
+
29
+ rb_define_singleton_method(mINIH, "parse", mINIH_parse, 1);
30
+ rb_define_singleton_method(mINIH, "load", mINIH_load, 1);
31
+ }
32
+
33
+ static int mINIH_ini_handler(void *data, const char *sect, const char *name, const char *val)
34
+ {
35
+ VALUE sect_s = rb_str_new_cstr(sect);
36
+ VALUE name_s = rb_str_new_cstr(name);
37
+ VALUE hash = *((VALUE *) data);
38
+ VALUE subh = rb_hash_aref(hash, sect_s);
39
+
40
+ if (NIL_P(subh)) {
41
+ subh = rb_hash_new();
42
+ }
43
+
44
+ rb_hash_aset(subh, name_s, rb_str_new_cstr(val));
45
+ rb_hash_aset(hash, sect_s, subh);
46
+
47
+ return 1;
48
+ }
49
+
50
+ static VALUE mINIH_parse(VALUE self, VALUE string)
51
+ {
52
+ char *str = StringValueCStr(string);
53
+ VALUE hash = rb_hash_new();
54
+ int result;
55
+
56
+ if ((result = ini_parse_string(str, mINIH_ini_handler, &hash)) != 0) {
57
+ rb_raise(rb_eRuntimeError, "parse error, line %d", result);
58
+ }
59
+
60
+ return rb_funcall(mINIH, rb_intern("normalize"), 1, hash);
61
+ }
62
+
63
+ static VALUE mINIH_load(VALUE self, VALUE filename)
64
+ {
65
+ char *file = StringValueCStr(filename);
66
+ VALUE hash = rb_hash_new();
67
+ int result;
68
+
69
+ if ((result = ini_parse(file, mINIH_ini_handler, &hash)) != 0) {
70
+ if (result < 0) {
71
+ rb_raise(rb_eRuntimeError, "I/O error");
72
+ }
73
+ else {
74
+ rb_raise(rb_eRuntimeError, "parse error, line %d", result);
75
+ }
76
+ }
77
+
78
+ return rb_funcall(mINIH, rb_intern("normalize"), 1, hash);
79
+ }
data/lib/inih.rb ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../ext/inih/inih"
4
+
5
+ # The primary namespace for {INIH}.
6
+ module INIH
7
+ # The current version of ruby-inih.
8
+ VERSION = "0.0.1"
9
+
10
+ # Normalize a parsed INI file's values.
11
+ # @api private
12
+ def self.normalize(hsh)
13
+ hsh.map do |k, sect|
14
+ [k, normalize_sect(sect)]
15
+ end.to_h
16
+ end
17
+
18
+ # Normalize the values in a section of a parsed INI file.
19
+ # @api private
20
+ def self.normalize_sect(sect)
21
+ sect.map do |k, v|
22
+ nv = case v
23
+ when "true" then true
24
+ when "false" then false
25
+ when /\A\d+\Z/ then Integer v
26
+ when /\A\d+\.\d+\Z/ then Float v
27
+ else v
28
+ end
29
+
30
+ [k, nv]
31
+ end.to_h
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inih
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - William Woodruff
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A native library for parsing INI files.
14
+ email: william@tuffbizz.com
15
+ executables: []
16
+ extensions:
17
+ - ext/inih/extconf.rb
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".yardopts"
21
+ - LICENSE
22
+ - README.md
23
+ - ext/inih/extconf.rb
24
+ - ext/inih/ini.c
25
+ - ext/inih/inih.c
26
+ - lib/inih.rb
27
+ homepage: https://github.com/woodruffw/ruby-ini
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.6.11
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: inih - a Ruby wrapper for a simple C INI parser
51
+ test_files: []