xrope is now the internal representation of pic_str

This commit is contained in:
Yuichi Nishiwaki 2014-02-27 21:54:37 +09:00
parent 8e511bc410
commit 8586dc9057
11 changed files with 85 additions and 56 deletions

View File

@ -36,6 +36,7 @@ extern "C" {
#include "xhash/xhash.h" #include "xhash/xhash.h"
#include "xfile/xfile.h" #include "xfile/xfile.h"
#include "xrope/xrope.h"
#if __STDC_VERSION__ >= 201112L #if __STDC_VERSION__ >= 201112L
# define NORETURN _Noreturn # define NORETURN _Noreturn

View File

@ -11,8 +11,7 @@ extern "C" {
struct pic_string { struct pic_string {
PIC_OBJECT_HEADER PIC_OBJECT_HEADER
char *str; xrope *rope;
size_t len;
}; };
#define pic_str_p(v) (pic_type(v) == PIC_TT_STRING) #define pic_str_p(v) (pic_type(v) == PIC_TT_STRING)
@ -30,6 +29,8 @@ pic_str *pic_strcat(pic_state *, pic_str *, pic_str *);
pic_str *pic_substr(pic_state *, pic_str *, size_t, size_t); pic_str *pic_substr(pic_state *, pic_str *, size_t, size_t);
int pic_strcmp(pic_str *, pic_str *); int pic_strcmp(pic_str *, pic_str *);
const char *pic_str_cstr(pic_str *);
pic_value pic_format(pic_state *, const char *, ...); pic_value pic_format(pic_state *, const char *, ...);
pic_value pic_vformat(pic_state *, const char *, va_list); pic_value pic_vformat(pic_state *, const char *, va_list);
pic_value pic_vfformat(pic_state *, xFILE *, const char *, va_list); pic_value pic_vfformat(pic_state *, xFILE *, const char *, va_list);

View File

@ -16,7 +16,7 @@ pic_errmsg(pic_state *pic)
{ {
assert(pic->err != NULL); assert(pic->err != NULL);
return pic->err->msg->str; return pic_str_cstr(pic->err->msg);
} }
NORETURN static void NORETURN static void

View File

@ -595,7 +595,7 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
break; break;
} }
case PIC_TT_STRING: { case PIC_TT_STRING: {
pic_free(pic, (void*)((struct pic_string *)obj)->str); XROPE_DECREF(((struct pic_string *)obj)->rope);
break; break;
} }
case PIC_TT_PORT: { case PIC_TT_PORT: {

View File

@ -619,11 +619,11 @@ pic_macro_include(pic_state *pic)
body = pic_list(pic, 1, pic_symbol_value(pic->sBEGIN)); body = pic_list(pic, 1, pic_symbol_value(pic->sBEGIN));
for (i = 0; i < argc; ++i) { for (i = 0; i < argc; ++i) {
char *filename; const char *filename;
if (! pic_str_p(argv[i])) { if (! pic_str_p(argv[i])) {
pic_error(pic, "expected string"); pic_error(pic, "expected string");
} }
filename = pic_str_ptr(argv[i])->str; filename = pic_str_cstr(pic_str_ptr(argv[i]));
file = fopen(filename, "r"); file = fopen(filename, "r");
if (file == NULL) { if (file == NULL) {
pic_error(pic, "could not open file"); pic_error(pic, "could not open file");

View File

@ -94,8 +94,7 @@ yy_str_new_cstr(struct parser_control *p, const char *cstr)
struct pic_string *str; struct pic_string *str;
str = (struct pic_string *)yy_obj_alloc(p, sizeof(struct pic_string), PIC_TT_STRING); str = (struct pic_string *)yy_obj_alloc(p, sizeof(struct pic_string), PIC_TT_STRING);
str->len = strlen(cstr); str->rope = xr_new_volatile(cstr, strlen(cstr));
str->str = pic_strdup(p->pic, cstr);
return pic_obj_value(str); return pic_obj_value(str);
} }

View File

@ -414,7 +414,7 @@ pic_port_read_line(pic_state *pic)
} }
str = pic_get_output_string(pic, buf); str = pic_get_output_string(pic, buf);
if (str->len == 0 && c == EOF) { if (pic_strlen(str) == 0 && c == EOF) {
return pic_eof_object(); return pic_eof_object();
} }
else { else {

View File

@ -9,24 +9,25 @@
#include "picrin/pair.h" #include "picrin/pair.h"
#include "picrin/port.h" #include "picrin/port.h"
pic_str * static pic_str *
pic_str_new(pic_state *pic, const char *cstr, size_t len) str_new_rope(pic_state *pic, xrope *rope)
{ {
pic_str *str; pic_str *str;
char *copy;
if (cstr) {
copy = pic_strdup(pic, cstr);
} else {
copy = (char *)pic_alloc(pic, len);
}
str = (pic_str *)pic_obj_alloc(pic, sizeof(pic_str), PIC_TT_STRING); str = (pic_str *)pic_obj_alloc(pic, sizeof(pic_str), PIC_TT_STRING);
str->len = len; str->rope = rope; /* delegate ownership */
str->str = copy;
return str; return str;
} }
pic_str *
pic_str_new(pic_state *pic, const char *imbed, size_t len)
{
if (imbed == NULL && len > 0) {
pic_errorf(pic, "zero length specified against NULL ptr");
}
return str_new_rope(pic, xr_new_volatile(imbed, len));
}
pic_str * pic_str *
pic_str_new_cstr(pic_state *pic, const char *cstr) pic_str_new_cstr(pic_state *pic, const char *cstr)
{ {
@ -38,73 +39,100 @@ pic_str_new_fill(pic_state *pic, size_t len, char fill)
{ {
size_t i; size_t i;
char *cstr; char *cstr;
pic_str *str;
cstr = (char *)pic_alloc(pic, len + 1); cstr = (char *)pic_alloc(pic, len + 1);
cstr[len] = '\0';
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
cstr[i] = fill; cstr[i] = fill;
} }
cstr[len] = '\0';
return pic_str_new(pic, cstr, len); str = pic_str_new(pic, cstr, len);
pic_free(pic, cstr);
return str;
} }
size_t size_t
pic_strlen(pic_str *str) pic_strlen(pic_str *str)
{ {
return str->len; return xr_len(str->rope);
} }
char char
pic_str_ref(pic_state *pic, pic_str *str, size_t n) pic_str_ref(pic_state *pic, pic_str *str, size_t i)
{ {
UNUSED(pic); char c;
return str->str[n]; c = xr_at(str->rope, i);
if (c == -1) {
pic_errorf(pic, "index out of range %d", i);
}
return c;
}
static xrope *
xr_put(xrope *rope, size_t i, char c)
{
xrope *x, *y;
char buf[1];
if (xr_len(rope) <= i) {
return NULL;
}
buf[0] = c;
x = xr_sub(rope, 0, i);
y = xr_new_volatile(buf, 1);
rope = xr_cat(x, y);
XROPE_DECREF(x);
XROPE_DECREF(y);
x = rope;
y = xr_sub(rope, i + 1, xr_len(rope));
rope = xr_cat(x, y);
XROPE_DECREF(x);
XROPE_DECREF(y);
return rope;
} }
void void
pic_str_set(pic_state *pic, pic_str *str, size_t i, char c) pic_str_set(pic_state *pic, pic_str *str, size_t i, char c)
{ {
UNUSED(pic); xrope *x;
str->str[i] = c; x = xr_put(str->rope, i, c);
if (x == NULL) {
pic_errorf(pic, "index out of range %d", i);
}
XROPE_DECREF(str->rope);
str->rope = x;
} }
pic_str * pic_str *
pic_strcat(pic_state *pic, pic_str *a, pic_str *b) pic_strcat(pic_state *pic, pic_str *a, pic_str *b)
{ {
size_t len; return str_new_rope(pic, xr_cat(a->rope, b->rope));
char *buf;
len = a->len + b->len;
buf = pic_alloc(pic, len + 1);
memcpy(buf, a->str, a->len);
memcpy(buf + a->len, b->str, b->len);
buf[len] = '\0';
return pic_str_new(pic, buf, len);
} }
pic_str * pic_str *
pic_substr(pic_state *pic, pic_str *str, size_t s, size_t e) pic_substr(pic_state *pic, pic_str *str, size_t s, size_t e)
{ {
size_t len; return str_new_rope(pic, xr_sub(str->rope, s, e));
char *buf;
len = e - s;
buf = pic_alloc(pic, len + 1);
memcpy(buf, str->str + s, len);
buf[len] = '\0';
return pic_str_new(pic, buf, len);
} }
int int
pic_strcmp(pic_str *str1, pic_str *str2) pic_strcmp(pic_str *str1, pic_str *str2)
{ {
return strcmp(str1->str, str2->str); return strcmp(xr_cstr(str1->rope), xr_cstr(str2->rope));
}
const char *
pic_str_cstr(pic_str *str)
{
return xr_cstr(str->rope);
} }
pic_value pic_value

View File

@ -93,7 +93,7 @@ pic_symbol_string_to_symbol(pic_state *pic)
pic_error(pic, "string->symbol: expected string"); pic_error(pic, "string->symbol: expected string");
} }
return pic_symbol_value(pic_intern_cstr(pic, pic_str_ptr(v)->str)); return pic_symbol_value(pic_intern_cstr(pic, pic_str_cstr(pic_str_ptr(v))));
} }
void void

View File

@ -188,15 +188,15 @@ pic_get_args(pic_state *pic, const char *format, ...)
} }
case 'z': { case 'z': {
pic_value str; pic_value str;
char **cstr; const char **cstr;
cstr = va_arg(ap, char **); cstr = va_arg(ap, const char **);
if (i < argc) { if (i < argc) {
str = GET_OPERAND(pic,i); str = GET_OPERAND(pic,i);
if (! pic_str_p(str)) { if (! pic_str_p(str)) {
pic_error(pic, "pic_get_args: expected string"); pic_error(pic, "pic_get_args: expected string");
} }
*cstr = pic_str_ptr(str)->str; *cstr = pic_str_cstr(pic_str_ptr(str));
i++; i++;
} }
break; break;

View File

@ -155,11 +155,11 @@ static void
write_str(pic_state *pic, struct pic_string *str, xFILE *file) write_str(pic_state *pic, struct pic_string *str, xFILE *file)
{ {
size_t i; size_t i;
const char *cstr = str->str; const char *cstr = pic_str_cstr(str);
UNUSED(pic); UNUSED(pic);
for (i = 0; i < str->len; ++i) { for (i = 0; i < pic_strlen(str); ++i) {
if (cstr[i] == '"' || cstr[i] == '\\') { if (cstr[i] == '"' || cstr[i] == '\\') {
xfputc('\\', file); xfputc('\\', file);
} }