habaki 0.5.0
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 +7 -0
- data/Gemfile +3 -0
- data/ext/katana/extconf.rb +20 -0
- data/ext/katana/rb_katana.c +280 -0
- data/ext/katana/rb_katana.h +102 -0
- data/ext/katana/rb_katana_array.c +144 -0
- data/ext/katana/rb_katana_declaration.c +389 -0
- data/ext/katana/rb_katana_rule.c +461 -0
- data/ext/katana/rb_katana_selector.c +559 -0
- data/ext/katana/src/foundation.c +237 -0
- data/ext/katana/src/foundation.h +120 -0
- data/ext/katana/src/katana.h +590 -0
- data/ext/katana/src/katana.lex.c +4104 -0
- data/ext/katana/src/katana.lex.h +592 -0
- data/ext/katana/src/katana.tab.c +4422 -0
- data/ext/katana/src/katana.tab.h +262 -0
- data/ext/katana/src/parser.c +1563 -0
- data/ext/katana/src/parser.h +237 -0
- data/ext/katana/src/selector.c +659 -0
- data/ext/katana/src/selector.h +54 -0
- data/ext/katana/src/tokenizer.c +300 -0
- data/ext/katana/src/tokenizer.h +41 -0
- data/lib/habaki/charset_rule.rb +25 -0
- data/lib/habaki/declaration.rb +53 -0
- data/lib/habaki/declarations.rb +346 -0
- data/lib/habaki/error.rb +43 -0
- data/lib/habaki/font_face_rule.rb +24 -0
- data/lib/habaki/formal_syntax.rb +464 -0
- data/lib/habaki/formatter.rb +99 -0
- data/lib/habaki/import_rule.rb +34 -0
- data/lib/habaki/media_rule.rb +173 -0
- data/lib/habaki/namespace_rule.rb +31 -0
- data/lib/habaki/node.rb +52 -0
- data/lib/habaki/page_rule.rb +24 -0
- data/lib/habaki/qualified_name.rb +29 -0
- data/lib/habaki/rule.rb +48 -0
- data/lib/habaki/rules.rb +225 -0
- data/lib/habaki/selector.rb +98 -0
- data/lib/habaki/selectors.rb +49 -0
- data/lib/habaki/style_rule.rb +35 -0
- data/lib/habaki/stylesheet.rb +158 -0
- data/lib/habaki/sub_selector.rb +234 -0
- data/lib/habaki/sub_selectors.rb +42 -0
- data/lib/habaki/supports_rule.rb +65 -0
- data/lib/habaki/value.rb +321 -0
- data/lib/habaki/values.rb +86 -0
- data/lib/habaki/visitor/element.rb +50 -0
- data/lib/habaki/visitor/media.rb +22 -0
- data/lib/habaki/visitor/nokogiri_element.rb +56 -0
- data/lib/habaki.rb +39 -0
- 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__) */
|