habaki 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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__) */
|