Track XML C lexer state in C only.

Instead of storing "act" and "cs" as an instance variable they (along with some
other variables) are now stored in a struct. This struct is attached to a lexer
instance using the (crappy) Data_Get_Struct/Data_Wrap_Struct API.
This commit is contained in:
Yorick Peterse 2014-10-26 11:38:06 +01:00
parent b304b8b077
commit d951a8cc87
2 changed files with 48 additions and 7 deletions

View File

@ -5,4 +5,12 @@
extern void Init_liboga_xml_lexer(); extern void Init_liboga_xml_lexer();
typedef struct {
int act;
int cs;
int lines;
int stack[4];
int top;
} OgaLexerState;
#endif #endif

View File

@ -75,11 +75,15 @@ void liboga_xml_lexer_callback_simple(VALUE self, const char *name)
*/ */
VALUE oga_xml_lexer_advance(VALUE self, VALUE data_block) VALUE oga_xml_lexer_advance(VALUE self, VALUE data_block)
{ {
OgaLexerState *state;
/* Make sure that all data passed back to Ruby has the proper encoding. */ /* Make sure that all data passed back to Ruby has the proper encoding. */
rb_encoding *encoding = rb_enc_get(data_block); rb_encoding *encoding = rb_enc_get(data_block);
char *data_str_val = StringValueCStr(data_block); char *data_str_val = StringValueCStr(data_block);
Data_Get_Struct(self, OgaLexerState, state);
const char *p = data_str_val; const char *p = data_str_val;
const char *pe = data_str_val + strlen(data_str_val); const char *pe = data_str_val + strlen(data_str_val);
const char *eof = pe; const char *eof = pe;
@ -87,14 +91,11 @@ VALUE oga_xml_lexer_advance(VALUE self, VALUE data_block)
const char *te = 0; const char *te = 0;
const char *mark = 0; const char *mark = 0;
int act = NUM2INT(oga_ivar_get(self, "@act")); int lines = state->lines;
int cs = NUM2INT(oga_ivar_get(self, "@cs"));
int lines = 0;
%% write exec; %% write exec;
oga_ivar_set(self, "@act", INT2NUM(act)); state->lines = lines;
oga_ivar_set(self, "@cs", INT2NUM(cs));
return Qnil; return Qnil;
} }
@ -104,14 +105,44 @@ VALUE oga_xml_lexer_advance(VALUE self, VALUE data_block)
*/ */
VALUE oga_xml_lexer_reset(VALUE self) VALUE oga_xml_lexer_reset(VALUE self)
{ {
oga_ivar_set(self, "@act", INT2NUM(0)); OgaLexerState *state;
oga_ivar_set(self, "@cs", INT2NUM(c_lexer_start));
Data_Get_Struct(self, OgaLexerState, state);
state->act = 0;
state->cs = c_lexer_start;
state->lines = 0;
state->top = 0;
return Qnil; return Qnil;
} }
/**
* Frees the associated lexer state struct.
*/
void oga_xml_lexer_free(void *state)
{
free((OgaLexerState *) state);
}
/**
* Allocates and wraps the C lexer state struct. This state is used to keep
* track of the current position, line numbers, etc.
*/
VALUE oga_xml_lexer_allocate(VALUE klass)
{
OgaLexerState *state = malloc(sizeof(OgaLexerState));
return Data_Wrap_Struct(klass, NULL, oga_xml_lexer_free, state);
}
%%{ %%{
include base_lexer "base_lexer.rl"; include base_lexer "base_lexer.rl";
variable top state->top;
variable stack state->stack;
variable act state->act;
variable cs state->cs;
}%% }%%
void Init_liboga_xml_lexer() void Init_liboga_xml_lexer()
@ -122,4 +153,6 @@ void Init_liboga_xml_lexer()
rb_define_method(cLexer, "advance_native", oga_xml_lexer_advance, 1); rb_define_method(cLexer, "advance_native", oga_xml_lexer_advance, 1);
rb_define_method(cLexer, "reset_native", oga_xml_lexer_reset, 0); rb_define_method(cLexer, "reset_native", oga_xml_lexer_reset, 0);
rb_define_alloc_func(cLexer, oga_xml_lexer_allocate);
} }