From ee59df9300a8391d7bb54af463d8cd138f2a824e Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com> Date: Wed, 10 May 2017 00:49:15 +0900 Subject: [PATCH] add pic_cstr --- contrib/20.r7rs/src/system.c | 2 +- lib/bool.c | 2 +- lib/ext/write.c | 34 +++++++++++++++--------- lib/include/picrin.h | 1 + lib/object.h | 2 ++ lib/port.c | 4 +-- lib/proc.c | 6 ++--- lib/state.c | 4 +-- lib/string.c | 50 +++++++++++++++++++++++++++++++++++- lib/symbol.c | 7 +++-- lib/vector.c | 6 ++--- 11 files changed, 89 insertions(+), 29 deletions(-) diff --git a/contrib/20.r7rs/src/system.c b/contrib/20.r7rs/src/system.c index 64979667..9f1c8c03 100644 --- a/contrib/20.r7rs/src/system.c +++ b/contrib/20.r7rs/src/system.c @@ -99,7 +99,7 @@ pic_system_getenvs(pic_state *pic) ; key = pic_str_value(pic, *envp, i); - val = pic_cstr_value(pic, getenv(pic_str(pic, key, NULL))); + val = pic_cstr_value(pic, getenv(pic_cstr(pic, key, NULL))); /* push */ data = pic_cons(pic, pic_cons(pic, key, val), data); diff --git a/lib/bool.c b/lib/bool.c index 3dbe050a..5fd28149 100644 --- a/lib/bool.c +++ b/lib/bool.c @@ -42,7 +42,7 @@ pic_equal_p(pic_state *pic, pic_value x, pic_value y) if (xlen != ylen) { return false; } - return strcmp(xstr, ystr) == 0; + return memcmp(xstr, ystr, xlen) == 0; } case PIC_TYPE_BLOB: { int xlen, ylen; diff --git a/lib/ext/write.c b/lib/ext/write.c index 8e5f384b..29bf5351 100644 --- a/lib/ext/write.c +++ b/lib/ext/write.c @@ -104,6 +104,15 @@ is_shared_object(pic_state *pic, pic_value obj, struct writer_control *p) { return pic_int(pic, pic_attr_ref(pic, shared, obj)) > 0; } +static void +write_symbol(pic_state *pic, pic_value sym, pic_value port) +{ + int len; + const char *buf = pic_str(pic, pic_sym_name(pic, sym), &len); + + pic_fwrite(pic, buf, len, 1, port); +} + static void write_blob(pic_state *pic, pic_value blob, pic_value port) { @@ -147,21 +156,21 @@ write_char(pic_state *pic, pic_value ch, pic_value port, struct writer_control * static void write_str(pic_state *pic, pic_value str, pic_value port, struct writer_control *p) { - int i; - const char *cstr = pic_str(pic, str, NULL); + int i, len; + const char *buf = pic_str(pic, str, &len); if (p->mode == DISPLAY_MODE) { - pic_fprintf(pic, port, "%s", pic_str(pic, str, NULL)); + pic_fwrite(pic, buf, len, 1, port); return; } - pic_fprintf(pic, port, "\""); - for (i = 0; i < pic_str_len(pic, str); ++i) { - if (cstr[i] == '"' || cstr[i] == '\\') { + pic_fputc(pic, '"', port); + for (i = 0; i < len; ++i) { + if (buf[i] == '"' || buf[i] == '\\') { pic_fputc(pic, '\\', port); } - pic_fputc(pic, cstr[i], port); + pic_fputc(pic, buf[i], port); } - pic_fprintf(pic, port, "\""); + pic_fputc(pic, '"', port); } static void @@ -202,8 +211,7 @@ write_pair_help(pic_state *pic, pic_value pair, pic_value port, struct writer_co } } -#define EQ(sym, lit) (strcmp(pic_str(pic, pic_sym_name(pic, sym), NULL), lit) == 0) -#define pic_sym(pic,sym) pic_str(pic, pic_sym_name(pic, (sym)), NULL) +#define EQ(sym, lit) (pic_eq_p(pic, sym, pic_intern_lit(pic, lit))) static void write_pair(pic_state *pic, pic_value pair, pic_value port, struct writer_control *p) @@ -281,7 +289,9 @@ write_dict(pic_state *pic, pic_value dict, pic_value port, struct writer_control pic_fprintf(pic, port, "#.(dictionary"); while (pic_dict_next(pic, dict, &it, &key, &val)) { - pic_fprintf(pic, port, " '%s ", pic_sym(pic, key)); + pic_fputs(pic, " '", port); + write_symbol(pic, key, port); + pic_fputc(pic, ' ', port); write_core(pic, val, port, p); } pic_fprintf(pic, port, ")"); @@ -387,7 +397,7 @@ write_core(pic_state *pic, pic_value obj, pic_value port, struct writer_control pic_fprintf(pic, port, "%d", pic_int(pic, obj)); break; case PIC_TYPE_SYMBOL: - pic_fprintf(pic, port, "%s", pic_sym(pic, obj)); + write_symbol(pic, obj, port); break; case PIC_TYPE_FLOAT: write_float(pic, obj, port); diff --git a/lib/include/picrin.h b/lib/include/picrin.h index a1676416..4e6f71a2 100644 --- a/lib/include/picrin.h +++ b/lib/include/picrin.h @@ -125,6 +125,7 @@ double pic_float(pic_state *, pic_value f); char pic_char(pic_state *, pic_value c); #define pic_bool(pic,b) (! pic_false_p(pic, (b))) const char *pic_str(pic_state *, pic_value str, int *len); +const char *pic_cstr(pic_state *, pic_value str, int *len); unsigned char *pic_blob(pic_state *, pic_value blob, int *len); void *pic_data(pic_state *, pic_value data); /* serialization */ diff --git a/lib/object.h b/lib/object.h index e3228a49..9507e376 100644 --- a/lib/object.h +++ b/lib/object.h @@ -223,6 +223,8 @@ pic_value pic_make_record(pic_state *, pic_value type, pic_value datum); pic_value pic_record_type(pic_state *pic, pic_value record); pic_value pic_record_datum(pic_state *pic, pic_value record); pic_value pic_make_cont(pic_state *pic, pic_value k); +int pic_str_hash(pic_state *pic, pic_value str); +int pic_str_cmp(pic_state *pic, pic_value str1, pic_value str2); struct rope *pic_rope_incref(struct rope *); void pic_rope_decref(pic_state *, struct rope *); diff --git a/lib/port.c b/lib/port.c index 1b2de81a..e4dca466 100644 --- a/lib/port.c +++ b/lib/port.c @@ -338,13 +338,13 @@ pic_vfprintf(pic_state *pic, pic_value port, const char *fmt, va_list ap) case 'i': { int ival = va_arg(ap, int); pic_value str = pic_funcall(pic, "number->string", 1, pic_int_value(pic, ival)); - pic_fputs(pic, pic_str(pic, str, 0), port); + pic_fputs(pic, pic_cstr(pic, str, 0), port); break; } case 'f': { double f = va_arg(ap, double); pic_value str = pic_funcall(pic, "number->string", 1, pic_float_value(pic, f)); - pic_fputs(pic, pic_str(pic, str, 0), port); + pic_fputs(pic, pic_cstr(pic, str, 0), port); break; } case 'c': { diff --git a/lib/proc.c b/lib/proc.c index 3cce822c..15d731f2 100644 --- a/lib/proc.c +++ b/lib/proc.c @@ -223,7 +223,7 @@ arg_error(pic_state *pic, int actual, bool varg, int expected) { const char *msg; - msg = pic_str(pic, pic_strf_value(pic, "wrong number of arguments (%d for %s%d)", actual, (varg ? "at least " : ""), expected), NULL); + msg = pic_cstr(pic, pic_strf_value(pic, "wrong number of arguments (%d for %s%d)", actual, (varg ? "at least " : ""), expected), NULL); pic_error(pic, msg, 0); } @@ -343,7 +343,7 @@ pic_get_args(pic_state *pic, const char *format, ...) } else { const char *msg; - msg = pic_str(pic, pic_strf_value(pic, "pic_get_args: data type \"%s\" required", type->type_name), NULL); + msg = pic_cstr(pic, pic_strf_value(pic, "pic_get_args: data type \"%s\" required", type->type_name), NULL); pic_error(pic, msg, 1, v); } break; @@ -412,7 +412,7 @@ pic_get_args(pic_state *pic, const char *format, ...) } VAL_CASE('c', char, char, pic_char(pic, v)) - VAL_CASE('z', str, const char *, pic_str(pic, v, NULL)) + VAL_CASE('z', str, const char *, pic_cstr(pic, v, NULL)) #define OBJ_CASE(c, type) VAL_CASE(c, type, pic_value, v) diff --git a/lib/state.c b/lib/state.c index 0095146e..f176f133 100644 --- a/lib/state.c +++ b/lib/state.c @@ -310,7 +310,7 @@ pic_warnf(pic_state *PIC_UNUSED(pic), const char *PIC_UNUSED(fmt), ...) va_start(ap, fmt); err = pic_vstrf_value(pic, fmt, ap); va_end(ap); - pic_fprintf(pic, pic_stderr(pic), "warn: %s\n", pic_str(pic, err, NULL)); + pic_fprintf(pic, pic_stderr(pic), "warn: %s\n", pic_cstr(pic, err, NULL)); #endif } @@ -352,7 +352,7 @@ pic_define(pic_state *pic, const char *name, pic_value val) pic_value sym = pic_intern_cstr(pic, name); if (pic_dict_has(pic, pic->globals, sym)) { - pic_warnf(pic, "redefining variable: %s", pic_str(pic, pic_sym_name(pic, sym), NULL)); + pic_warnf(pic, "redefining variable: %s", name); } pic_dict_set(pic, pic->globals, sym, val); } diff --git a/lib/string.c b/lib/string.c index 24531ae1..b59a7551 100644 --- a/lib/string.c +++ b/lib/string.c @@ -267,6 +267,38 @@ pic_str_sub(pic_state *pic, pic_value str, int s, int e) return make_str(pic, slice(pic, str_ptr(pic, str)->rope, s, e)); } +int +pic_str_hash(pic_state *pic, pic_value str) +{ + int len, h = 0; + const char *s; + + s = pic_str(pic, str, &len); + while (len-- > 0) { + h = (h << 5) - h + *s++; + } + return h; +} + +int +pic_str_cmp(pic_state *pic, pic_value str1, pic_value str2) +{ + int len1, len2, r; + const char *buf1, *buf2; + + buf1 = pic_str(pic, str1, &len1); + buf2 = pic_str(pic, str2, &len2); + + if (len1 == len2) { + return memcmp(buf1, buf2, len1); + } + r = memcmp(buf1, buf2, (len1 < len2 ? len1 : len2)); + if (r != 0) { + return r; + } + return len1 - len2; +} + const char * pic_str(pic_state *pic, pic_value str, int *len) { @@ -287,6 +319,22 @@ pic_str(pic_state *pic, pic_value str, int *len) return r->u.leaf.str; } +const char * +pic_cstr(pic_state *pic, pic_value str, int *len) +{ + const char *buf; + int l; + + buf = pic_str(pic, str, &l); + if (strchr(buf, '\0') != buf + l) { + pic_error(pic, "casting scheme string containing null character to c string", 1, str); + } + if (len) { + *len = l; + } + return buf; +} + static pic_value pic_str_string_p(pic_state *pic) { @@ -398,7 +446,7 @@ pic_str_string_set(pic_state *pic) if (! pic_str_p(pic, argv[i])) { \ return pic_false_value(pic); \ } \ - if (! (strcmp(pic_str(pic, argv[i-1], NULL), pic_str(pic, argv[i], NULL)) op 0)) { \ + if (! (pic_str_cmp(pic, argv[i-1], argv[i]) op 0)) { \ return pic_false_value(pic); \ } \ } \ diff --git a/lib/symbol.c b/lib/symbol.c index 56b101de..301b41cd 100644 --- a/lib/symbol.c +++ b/lib/symbol.c @@ -8,11 +8,10 @@ #include "state.h" /* FIXME: arena is consumed every time hash/cmp is executed */ -#define to_cstr(a) (pic_str(pic, obj_value(pic, a), NULL)) -#define kh_pic_str_hash(a) (kh_str_hash_func(to_cstr(a))) -#define kh_pic_str_cmp(a, b) (kh_str_cmp_func(to_cstr(a), to_cstr(b))) +#define kh_pic_str_hash(a) (pic_str_hash(pic, obj_value(pic, (a)))) +#define kh_pic_str_equal(a,b) (pic_str_cmp(pic, obj_value(pic, (a)), obj_value(pic, (b))) == 0) -KHASH_DEFINE(oblist, struct string *, struct symbol *, kh_pic_str_hash, kh_pic_str_cmp) +KHASH_DEFINE(oblist, struct string *, struct symbol *, kh_pic_str_hash, kh_pic_str_equal) pic_value pic_intern(pic_state *pic, pic_value str) diff --git a/lib/vector.c b/lib/vector.c index 5073f7d0..992059cd 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -369,11 +369,11 @@ pic_vec_string_to_vector(pic_state *pic) { pic_value str, vec; int n, start, end, len, i; - const char *cstr; + const char *buf; n = pic_get_args(pic, "s|ii", &str, &start, &end); - cstr = pic_str(pic, str, &len); + buf = pic_str(pic, str, &len); switch (n) { case 1: @@ -387,7 +387,7 @@ pic_vec_string_to_vector(pic_state *pic) vec = pic_make_vec(pic, end - start, NULL); for (i = 0; i < end - start; ++i) { - pic_vec_set(pic, vec, i, pic_char_value(pic, cstr[i + start])); + pic_vec_set(pic, vec, i, pic_char_value(pic, buf[i + start])); } return vec; }