habaki 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/ext/katana/extconf.rb +20 -0
  4. data/ext/katana/rb_katana.c +280 -0
  5. data/ext/katana/rb_katana.h +102 -0
  6. data/ext/katana/rb_katana_array.c +144 -0
  7. data/ext/katana/rb_katana_declaration.c +389 -0
  8. data/ext/katana/rb_katana_rule.c +461 -0
  9. data/ext/katana/rb_katana_selector.c +559 -0
  10. data/ext/katana/src/foundation.c +237 -0
  11. data/ext/katana/src/foundation.h +120 -0
  12. data/ext/katana/src/katana.h +590 -0
  13. data/ext/katana/src/katana.lex.c +4104 -0
  14. data/ext/katana/src/katana.lex.h +592 -0
  15. data/ext/katana/src/katana.tab.c +4422 -0
  16. data/ext/katana/src/katana.tab.h +262 -0
  17. data/ext/katana/src/parser.c +1563 -0
  18. data/ext/katana/src/parser.h +237 -0
  19. data/ext/katana/src/selector.c +659 -0
  20. data/ext/katana/src/selector.h +54 -0
  21. data/ext/katana/src/tokenizer.c +300 -0
  22. data/ext/katana/src/tokenizer.h +41 -0
  23. data/lib/habaki/charset_rule.rb +25 -0
  24. data/lib/habaki/declaration.rb +53 -0
  25. data/lib/habaki/declarations.rb +346 -0
  26. data/lib/habaki/error.rb +43 -0
  27. data/lib/habaki/font_face_rule.rb +24 -0
  28. data/lib/habaki/formal_syntax.rb +464 -0
  29. data/lib/habaki/formatter.rb +99 -0
  30. data/lib/habaki/import_rule.rb +34 -0
  31. data/lib/habaki/media_rule.rb +173 -0
  32. data/lib/habaki/namespace_rule.rb +31 -0
  33. data/lib/habaki/node.rb +52 -0
  34. data/lib/habaki/page_rule.rb +24 -0
  35. data/lib/habaki/qualified_name.rb +29 -0
  36. data/lib/habaki/rule.rb +48 -0
  37. data/lib/habaki/rules.rb +225 -0
  38. data/lib/habaki/selector.rb +98 -0
  39. data/lib/habaki/selectors.rb +49 -0
  40. data/lib/habaki/style_rule.rb +35 -0
  41. data/lib/habaki/stylesheet.rb +158 -0
  42. data/lib/habaki/sub_selector.rb +234 -0
  43. data/lib/habaki/sub_selectors.rb +42 -0
  44. data/lib/habaki/supports_rule.rb +65 -0
  45. data/lib/habaki/value.rb +321 -0
  46. data/lib/habaki/values.rb +86 -0
  47. data/lib/habaki/visitor/element.rb +50 -0
  48. data/lib/habaki/visitor/media.rb +22 -0
  49. data/lib/habaki/visitor/nokogiri_element.rb +56 -0
  50. data/lib/habaki.rb +39 -0
  51. metadata +190 -0
@@ -0,0 +1,237 @@
1
+ //
2
+ // foundation.c
3
+ // Katana
4
+ //
5
+ // Created by QFish on 3/19/15.
6
+ // Copyright (c) 2015 QFish. All rights reserved.
7
+ //
8
+
9
+ #include "foundation.h"
10
+ #include "parser.h"
11
+
12
+ #include <string.h>
13
+ #include <strings.h>
14
+ #include <stdbool.h>
15
+ #include <assert.h>
16
+
17
+ //#undef assert
18
+ //#define assert(x)
19
+
20
+ struct KatanaInternalParser;
21
+
22
+ const KatanaParserString kKatanaAsteriskString = {"*", 1};
23
+
24
+ static const size_t kDefaultStringBufferSize = 12;
25
+
26
+ static void maybe_resize_string(struct KatanaInternalParser* parser,
27
+ size_t additional_chars,
28
+ KatanaParserString* str) {
29
+ size_t new_length = str->length + additional_chars;
30
+ size_t new_capacity = str->capacity;
31
+ while (new_capacity < new_length) {
32
+ new_capacity *= 2;
33
+ }
34
+ if (new_capacity != str->capacity) {
35
+ char* new_data = katana_parser_allocate(parser, new_capacity);
36
+ memset(new_data, 0, str->length);
37
+ memcpy(new_data, str->data, str->length);
38
+ katana_parser_deallocate(parser, str->data);
39
+ str->data = new_data;
40
+ str->capacity = new_capacity;
41
+ }
42
+ }
43
+
44
+ void katana_string_init(struct KatanaInternalParser* parser,
45
+ KatanaParserString* output) {
46
+ output->data = katana_parser_allocate(parser, kDefaultStringBufferSize);
47
+ memset( output->data, 0, sizeof(kDefaultStringBufferSize) );
48
+ output->length = 0;
49
+ output->capacity = kDefaultStringBufferSize;
50
+ }
51
+
52
+ void katana_string_append_characters(struct KatanaInternalParser* parser,
53
+ const char* str, KatanaParserString* output)
54
+ {
55
+ size_t len = strlen(str);
56
+ maybe_resize_string(parser, len, output);
57
+ memcpy(output->data + output->length, str, len);
58
+ output->length += len;
59
+ }
60
+
61
+ void katana_string_prepend_characters(struct KatanaInternalParser* parser,
62
+ const char* str,
63
+ KatanaParserString* output)
64
+ {
65
+ size_t len = strlen(str);
66
+ size_t new_length = output->length + len;
67
+ char* new_data = katana_parser_allocate(parser, new_length);
68
+ memcpy(new_data, str, len);
69
+ memcpy(new_data+len, output->data, output->length);
70
+ katana_parser_deallocate(parser, output->data);
71
+ output->data = new_data;
72
+ output->length = new_length;
73
+ output->capacity = new_length;
74
+ }
75
+
76
+ void katana_string_append_string(struct KatanaInternalParser* parser,
77
+ KatanaParserString* str,
78
+ KatanaParserString* output) {
79
+ maybe_resize_string(parser, str->length, output);
80
+ memcpy(output->data + output->length, str->data, str->length);
81
+ output->length += str->length;
82
+ }
83
+
84
+ bool katana_string_has_prefix(const char* str, const char* prefix)
85
+ {
86
+ size_t pre_len = strlen(prefix);
87
+ size_t str_len = strlen(str);
88
+ return pre_len <= str_len && strncasecmp(prefix, str, pre_len);
89
+ }
90
+
91
+ void katana_string_to_lowercase(struct KatanaInternalParser* parser,
92
+ KatanaParserString* str)
93
+ {
94
+ if ( !str )
95
+ return;
96
+ // FIXME: @(QFish) the char* in string piece is const, to find a better way
97
+ char *c = (char*)str->data;
98
+ for (int i=0; i < str->length; i++) {
99
+ *c = tolower(*c);
100
+ c++;
101
+ }
102
+ }
103
+
104
+
105
+
106
+ const char* katana_string_to_characters(struct KatanaInternalParser * parser, const KatanaParserString* str)
107
+ {
108
+ assert(NULL != str);
109
+ if (NULL == str)
110
+ return NULL;
111
+
112
+ char* buffer = katana_parser_allocate(parser, sizeof(char) * (str->length + 1));
113
+ memcpy(buffer, str->data, str->length);
114
+ buffer[str->length] = '\0';
115
+ return buffer;
116
+ }
117
+
118
+ const char* katana_string_to_characters_with_prefix_char(struct KatanaInternalParser * parser, const KatanaParserString* str, const char prefix)
119
+ {
120
+ assert(str);
121
+ if (NULL == str)
122
+ return NULL;
123
+
124
+ char* buffer = katana_parser_allocate(parser, sizeof(char) * (str->length + 2));
125
+ memcpy((buffer + 1), str->data, str->length);
126
+ buffer[0] = prefix;
127
+ buffer[str->length] = '\0';
128
+ return buffer;
129
+ }
130
+
131
+ /**
132
+ * Array
133
+ */
134
+ void katana_array_init(struct KatanaInternalParser* parser,
135
+ size_t initial_capacity, KatanaArray* array) {
136
+ array->length = 0;
137
+ array->capacity = (unsigned int)initial_capacity;
138
+ if (initial_capacity > 0) {
139
+ array->data = katana_parser_allocate(parser, sizeof(void*) * initial_capacity);
140
+ } else {
141
+ array->data = NULL;
142
+ }
143
+ }
144
+
145
+ void katana_array_destroy(struct KatanaInternalParser* parser,
146
+ KatanaArray* array) {
147
+ if (array->capacity > 0) {
148
+ katana_parser_deallocate(parser, array->data);
149
+ }
150
+ }
151
+
152
+ static void enlarge_array_if_full(struct KatanaInternalParser* parser,
153
+ KatanaArray* array) {
154
+ if (array->length >= array->capacity) {
155
+ if (array->capacity) {
156
+ size_t old_num_bytes = sizeof(void*) * array->capacity;
157
+ array->capacity *= 2;
158
+ size_t num_bytes = sizeof(void*) * array->capacity;
159
+ void** temp = katana_parser_allocate(parser, num_bytes);
160
+ memcpy(temp, array->data, old_num_bytes);
161
+ katana_parser_deallocate(parser, array->data);
162
+ array->data = temp;
163
+ } else {
164
+ // 0-capacity array; no previous array to deallocate.
165
+ array->capacity = 2;
166
+ array->data = katana_parser_allocate(parser, sizeof(void*) * array->capacity);
167
+ }
168
+ }
169
+ }
170
+
171
+ void katana_array_add(struct KatanaInternalParser* parser,
172
+ void* element, KatanaArray* array) {
173
+ enlarge_array_if_full(parser, array);
174
+ assert(array->data);
175
+ assert(array->length < array->capacity);
176
+ array->data[array->length++] = element;
177
+ }
178
+
179
+ void* katana_array_pop(struct KatanaInternalParser* parser,
180
+ KatanaArray* array) {
181
+ if (array->length == 0) {
182
+ return NULL;
183
+ }
184
+ return array->data[--array->length];
185
+ }
186
+
187
+ int katana_array_index_of(KatanaArray* array, void* element) {
188
+ for (int i = 0; i < array->length; ++i) {
189
+ if (array->data[i] == element) {
190
+ return i;
191
+ }
192
+ }
193
+ return -1;
194
+ }
195
+
196
+ void katana_array_insert_at(struct KatanaInternalParser* parser,
197
+ void* element, int index,
198
+ KatanaArray* array) {
199
+ assert(index >= 0);
200
+ assert(index <= array->length);
201
+ enlarge_array_if_full(parser, array);
202
+ ++array->length;
203
+ memmove(&array->data[index + 1], &array->data[index],
204
+ sizeof(void*) * (array->length - index - 1));
205
+ array->data[index] = element;
206
+ }
207
+
208
+ void katana_array_remove(struct KatanaInternalParser* parser,
209
+ void* node, KatanaArray* array) {
210
+ int index = katana_array_index_of(array, node);
211
+ if (index == -1) {
212
+ return;
213
+ }
214
+ katana_array_remove_at(parser, index, array);
215
+ }
216
+
217
+ void* katana_array_remove_at(struct KatanaInternalParser* parser,
218
+ int index, KatanaArray* array) {
219
+ assert(index >= 0);
220
+ assert(index < array->length);
221
+ void* result = array->data[index];
222
+ memmove(&array->data[index], &array->data[index + 1],
223
+ sizeof(void*) * (array->length - index - 1));
224
+ --array->length;
225
+ return result;
226
+ }
227
+
228
+ /**
229
+ * An alloc / free method
230
+ */
231
+ void* katana_parser_allocate(struct KatanaInternalParser* parser, size_t size) {
232
+ return parser->options->allocator(parser->options->userdata, size);
233
+ }
234
+
235
+ void katana_parser_deallocate(struct KatanaInternalParser* parser, void* ptr) {
236
+ parser->options->deallocator(parser->options->userdata, ptr);
237
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Copyright (c) 2015 QFish <im@qfi.sh>
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
21
+ */
22
+
23
+ #ifndef __Katana__foundation__
24
+ #define __Katana__foundation__
25
+
26
+ #include <stdio.h>
27
+ #include <ctype.h>
28
+
29
+ #ifdef __cplusplus
30
+ extern "C" {
31
+ #endif
32
+
33
+ #include "katana.h"
34
+
35
+ struct KatanaInternalParser;
36
+
37
+ /**
38
+ * String
39
+ */
40
+ typedef struct {
41
+ char* data;
42
+ size_t length;
43
+ size_t capacity;
44
+ } KatanaParserString;
45
+
46
+ extern const KatanaParserString kKatanaAsteriskString;
47
+
48
+ void katana_string_to_lowercase(struct KatanaInternalParser* parser, KatanaParserString* string);
49
+
50
+ // Initializes a new KatanaParserString.
51
+ void katana_string_init(struct KatanaInternalParser* parser, KatanaParserString* output);
52
+
53
+ // Appends some characters onto the end of the KatanaParserString.
54
+ void katana_string_append_characters(struct KatanaInternalParser* parser, const char* str, KatanaParserString* output);
55
+
56
+ // Prepends some characters at the start of the KatanaParserString.
57
+ void katana_string_prepend_characters(struct KatanaInternalParser* parser, const char* str, KatanaParserString* output);
58
+
59
+ // Transforms a KatanaParserString to characters.
60
+ const char* katana_string_to_characters(struct KatanaInternalParser * parser, const KatanaParserString* str);
61
+ // Transforms a KatanaParserString to characters with a char prepended at the start of the KatanaParserString.
62
+ const char* katana_string_to_characters_with_prefix_char(struct KatanaInternalParser * parser, const KatanaParserString* str, const char prefix);
63
+
64
+ // Appends a string onto the end of the KatanaParserString.
65
+ void katana_string_append_string(struct KatanaInternalParser* parser, KatanaParserString* str, KatanaParserString* output);
66
+ // Returns a bool value that indicates whether a given string matches the beginning characters of the receiver.
67
+ bool katana_string_has_prefix(const char* str, const char* prefix);
68
+
69
+ /**
70
+ * Number
71
+ */
72
+ typedef struct {
73
+ KatanaParserString raw;
74
+ double val;
75
+ } KatanaParserNumber;
76
+
77
+ /**
78
+ * Array
79
+ */
80
+ // Initializes a new KatanaArray with the specified initial capacity.
81
+ void katana_array_init(struct KatanaInternalParser* parser, size_t initial_capacity,
82
+ KatanaArray* array);
83
+
84
+ // Frees the memory used by an KatanaArray. Does not free the contained
85
+ // pointers, but you should free the pointers if necessary.
86
+ void katana_array_destroy(struct KatanaInternalParser* parser, KatanaArray* array);
87
+
88
+ // Adds a new element to an KatanaArray.
89
+ void katana_array_add(struct KatanaInternalParser* parser, void* element, KatanaArray* array);
90
+
91
+ // Removes and returns the element most recently added to the KatanaArray.
92
+ // Ownership is transferred to caller. Capacity is unchanged. If the array is
93
+ // empty, NULL is returned.
94
+ void* katana_array_pop(struct KatanaInternalParser* parser, KatanaArray* array);
95
+
96
+ // Inserts an element at a specific index. This is potentially O(N) time, but
97
+ // is necessary for some of the spec's behavior.
98
+ void katana_array_insert_at(struct KatanaInternalParser* parser, void* element, int index,
99
+ KatanaArray* array);
100
+
101
+ // Removes an element from the array, or does nothing if the element is not in
102
+ // the array.
103
+ void katana_array_remove(struct KatanaInternalParser* parser, void* element, KatanaArray* array);
104
+
105
+ // Removes and returns an element at a specific index. Note that this is
106
+ // potentially O(N) time and should be used sparingly.
107
+ void* katana_array_remove_at(struct KatanaInternalParser* parser, int index, KatanaArray* array);
108
+
109
+ /**
110
+ * An alloc / free method wrapper
111
+ */
112
+ void* katana_parser_allocate(struct KatanaInternalParser* parser, size_t size);
113
+ void katana_parser_deallocate(struct KatanaInternalParser* parser, void* ptr);
114
+
115
+ #ifdef __cplusplus
116
+ }
117
+ #endif
118
+
119
+
120
+ #endif /* defined(__Katana__foundation__) */