Created
November 8, 2009 00:53
-
-
Save pmichaud/229000 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
orange:~/parrot/trunk$ cat cs.patch | |
Index: src/pmc/codestring.pmc | |
=================================================================== | |
--- src/pmc/codestring.pmc (revision 42340) | |
+++ src/pmc/codestring.pmc (working copy) | |
@@ -35,11 +35,43 @@ | |
#endif | |
pmclass CodeString extends String provides string auto_attrs { | |
- ATTR INTVAL last_line_number; /* most recent line number seen */ | |
- ATTR INTVAL last_pos; /* most recent byte position seen */ | |
+ ATTR PMC *linepos; /* start of line positions */ | |
/* | |
+=item C<init()> | |
+ | |
+Initialize the CodeString. | |
+ | |
+=cut | |
+ | |
+*/ | |
+ | |
+ VTABLE void init() { | |
+ Parrot_CodeString_attributes * const attrs = PARROT_CODESTRING(SELF); | |
+ SUPER(); | |
+ attrs->linepos = PMCNULL; | |
+ PObj_custom_mark_SET(SELF); | |
+ } | |
+ | |
+/* | |
+ | |
+=item C<mark()> | |
+ | |
+Mark the CodeString as live. | |
+ | |
+=cut | |
+ | |
+*/ | |
+ | |
+ VTABLE void mark() { | |
+ Parrot_CodeString_attributes * const attrs = PARROT_CODESTRING(SELF); | |
+ if (!attrs) return; | |
+ Parrot_gc_mark_PMC_alive(INTERP, attrs->linepos); | |
+ } | |
+ | |
+/* | |
+ | |
=item C<emit(string fmt [, pmc args ] [, pmc hash ])> | |
Add a line to a C<CodeString> object according to C<fmt>. | |
@@ -125,7 +157,7 @@ | |
VTABLE_set_string_native(INTERP, SELF, S1); | |
RETURN(PMC *SELF); | |
-} | |
+ } | |
/* | |
@@ -140,54 +172,55 @@ | |
*/ | |
METHOD lineof(INTVAL pos) { | |
- STRING *str = NULL; | |
- INTVAL line = 0; | |
- INTVAL ipos = 0; | |
- INTVAL seen_first_line = 0; | |
- INTVAL jpos; | |
- INTVAL last_pos; | |
+ PMC *linepos; | |
+ INTVAL line; | |
+ INTVAL count; | |
- GET_ATTR_last_pos(INTERP, SELF, last_pos); | |
+ GET_ATTR_linepos(INTERP, SELF, linepos); | |
- /* the previous line number for this position is the same */ | |
- if (last_pos == pos) { | |
- GET_ATTR_last_line_number(INTERP, SELF, line); | |
- RETURN(INTVAL line); | |
- } | |
+ /* build the linepos array if we haven't already done so */ | |
+ if (!linepos || PMC_IS_NULL(linepos)) { | |
+ STRING *str = NULL; | |
+ INTVAL eos; | |
+ INTVAL jpos; | |
- /* start from the previous max line number and position */ | |
- if (last_pos < pos) { | |
- GET_ATTR_last_line_number(INTERP, SELF, line); | |
- ipos = last_pos; | |
- } | |
- | |
- GET_ATTR_str_val(INTERP, SELF, str); | |
- jpos = Parrot_str_find_cclass(INTERP, enum_cclass_newline, str, ipos, pos); | |
- | |
- while (jpos < pos) { | |
- | |
- if (ipos | |
- && jpos == ipos | |
- && string_ord(INTERP, str, jpos) == 10 | |
- && string_ord(INTERP, str, ipos - 1) == 13) { | |
- /* do not increment line; \r\n is a single line separator */ | |
+ linepos = pmc_new(INTERP, enum_class_ResizableIntegerArray); | |
+ /* get the string itself */ | |
+ GET_ATTR_str_val(INTERP, SELF, str); | |
+ eos = Parrot_str_byte_length(INTERP, str); | |
+ /* find the first newline, if any */ | |
+ jpos = Parrot_str_find_cclass(INTERP, enum_cclass_newline, | |
+ str, 0, eos); | |
+ while (jpos < eos) { | |
+ jpos++; | |
+ /* treat \r\n as a single newline */ | |
+ if (jpos < eos | |
+ && string_ord(INTERP, str, jpos - 1) == 10 | |
+ && string_ord(INTERP, str, jpos) == 13) { | |
+ jpos++; | |
+ } | |
+ /* add the start of line position */ | |
+ VTABLE_push_integer(INTERP, linepos, jpos); | |
+ /* search for the next newline */ | |
+ jpos = Parrot_str_find_cclass(INTERP, enum_cclass_newline, | |
+ str, jpos, eos); | |
} | |
- else | |
- line++; | |
- | |
- ipos = jpos + 1; | |
- | |
- jpos = Parrot_str_find_cclass(INTERP, enum_cclass_newline, str, ipos, pos); | |
+ /* save the array of line positions */ | |
+ SET_ATTR_linepos(INTERP, SELF, linepos); | |
} | |
- /* cache this position and line number for next time */ | |
- if (pos > last_pos) { | |
- SET_ATTR_last_pos(INTERP, SELF, jpos); | |
- SET_ATTR_last_line_number(INTERP, SELF, line); | |
- } | |
+ /* Find the line from the array, stop at the first index that is | |
+ * greater than the position we're looking for. We do a linear | |
+ * search for now, * perhaps a binary search would be better someday. | |
+ */ | |
+ count = VTABLE_elements(INTERP, linepos); | |
+ line = 0; | |
+ while (line < count | |
+ && VTABLE_get_integer_keyed_int(INTERP, linepos, line) < pos) | |
+ line++; | |
RETURN(INTVAL line); | |
-} | |
+ } | |
/* |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment