diff --git a/contrib/40.srfi/src/106.c b/contrib/40.srfi/src/106.c index c8efc474..a52d161d 100644 --- a/contrib/40.srfi/src/106.c +++ b/contrib/40.srfi/src/106.c @@ -185,8 +185,7 @@ pic_socket_socket_accept(pic_state *pic) static pic_value pic_socket_socket_send(pic_state *pic) { - pic_value obj; - struct pic_blob *bv; + pic_value obj, bv; const unsigned char *cursor; int flags = 0, remain, written; struct pic_socket_t *sock; @@ -223,7 +222,6 @@ static pic_value pic_socket_socket_recv(pic_state *pic) { pic_value obj; - struct pic_blob *bv; void *buf; int size; int flags = 0; @@ -239,7 +237,7 @@ pic_socket_socket_recv(pic_state *pic) sock = pic_socket_data(pic, obj); ensure_socket_is_open(pic, sock); - buf = malloc(size); + buf = pic_blob(pic, pic_blob_value(pic, NULL, size), NULL); if (buf == NULL && size > 0) { /* XXX: Is it really OK? */ pic_panic(pic, "memory exhausted"); @@ -251,14 +249,10 @@ pic_socket_socket_recv(pic_state *pic) } while (len < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); if (len < 0) { - free(buf); pic_errorf(pic, "%s", strerror(errno)); } - bv = pic_blob_value(pic, buf, len); - free(buf); - - return pic_obj_value(bv); + return pic_blob_value(pic, buf, len); } static pic_value diff --git a/extlib/benz/blob.c b/extlib/benz/blob.c index 6cc1eaac..125c3e74 100644 --- a/extlib/benz/blob.c +++ b/extlib/benz/blob.c @@ -5,7 +5,7 @@ #include "picrin.h" #include "picrin/object.h" -struct pic_blob * +pic_value pic_blob_value(pic_state *pic, const unsigned char *buf, int len) { struct pic_blob *bv; @@ -16,14 +16,16 @@ pic_blob_value(pic_state *pic, const unsigned char *buf, int len) if (buf) { memcpy(bv->data, buf, len); } - return bv; + return pic_obj_value(bv); } unsigned char * -pic_blob(pic_state PIC_UNUSED(*pic), struct pic_blob *blob, int *len) +pic_blob(pic_state PIC_UNUSED(*pic), pic_value blob, int *len) { - *len = blob->len; - return blob->data; + if (len) { + *len = pic_blob_ptr(pic, blob)->len; + } + return pic_blob_ptr(pic, blob)->data; } static pic_value @@ -39,16 +41,15 @@ pic_blob_bytevector_p(pic_state *pic) static pic_value pic_blob_bytevector(pic_state *pic) { - pic_value *argv; + pic_value *argv, blob; int argc, i; - struct pic_blob *blob; unsigned char *data; pic_get_args(pic, "*", &argc, &argv); blob = pic_blob_value(pic, 0, argc); - data = blob->data; + data = pic_blob(pic, blob, NULL); for (i = 0; i < argc; ++i) { pic_assert_type(pic, argv[i], int); @@ -60,91 +61,103 @@ pic_blob_bytevector(pic_state *pic) *data++ = (unsigned char)pic_int(pic, argv[i]); } - return pic_obj_value(blob); + return blob; } static pic_value pic_blob_make_bytevector(pic_state *pic) { - struct pic_blob *blob; - int k, i, b = 0; + pic_value blob; + int k, b = 0; pic_get_args(pic, "i|i", &k, &b); if (b < 0 || b > 255) pic_errorf(pic, "byte out of range"); - blob = pic_blob_value(pic, 0, k); - for (i = 0; i < k; ++i) { - blob->data[i] = (unsigned char)b; + if (k < 0) { + pic_errorf(pic, "make-bytevector: negative length given %d", k); } - return pic_obj_value(blob); + blob = pic_blob_value(pic, 0, k); + + memset(pic_blob(pic, blob, NULL), k, (unsigned char)b); + + return blob; } static pic_value pic_blob_bytevector_length(pic_state *pic) { - struct pic_blob *bv; + pic_value bv; + int len; pic_get_args(pic, "b", &bv); - return pic_int_value(pic, bv->len); + pic_blob(pic, bv, &len); + + return pic_int_value(pic, len); } static pic_value pic_blob_bytevector_u8_ref(pic_state *pic) { - struct pic_blob *bv; - int k; + pic_value bv; + unsigned char *buf; + int k, len; pic_get_args(pic, "bi", &bv, &k); - return pic_int_value(pic, bv->data[k]); + buf = pic_blob(pic, bv, &len); + + VALID_INDEX(pic, len, k); + + return pic_int_value(pic, buf[k]); } static pic_value pic_blob_bytevector_u8_set(pic_state *pic) { - struct pic_blob *bv; - int k, v; + pic_value bv; + unsigned char *buf; + int k, v, len; pic_get_args(pic, "bii", &bv, &k, &v); if (v < 0 || v > 255) pic_errorf(pic, "byte out of range"); - bv->data[k] = (unsigned char)v; + buf = pic_blob(pic, bv, &len); + + VALID_INDEX(pic, len, k); + + buf[k] = (unsigned char)v; + return pic_undef_value(pic); } static pic_value pic_blob_bytevector_copy_i(pic_state *pic) { - struct pic_blob *to, *from; - int n, at, start, end; + pic_value to, from; + unsigned char *tobuf, *frombuf; + int n, at, start, end, tolen, fromlen; n = pic_get_args(pic, "bib|ii", &to, &at, &from, &start, &end); + tobuf = pic_blob(pic, to, &tolen); + frombuf = pic_blob(pic, from, &fromlen); + switch (n) { case 3: start = 0; case 4: - end = from->len; + end = fromlen; } - if (to == from && (start <= at && at < end)) { - /* copy in reversed order */ - at += end - start; - while (start < end) { - to->data[--at] = from->data[--end]; - } - return pic_undef_value(pic); - } + VALID_ATRANGE(pic, tolen, at, fromlen, start, end); - while (start < end) { - to->data[at++] = from->data[start++]; - } + memmove(tobuf + at, frombuf + start, end - start); return pic_undef_value(pic); } @@ -152,62 +165,59 @@ pic_blob_bytevector_copy_i(pic_state *pic) static pic_value pic_blob_bytevector_copy(pic_state *pic) { - struct pic_blob *from, *to; - int n, start, end, i = 0; + pic_value from; + unsigned char *buf; + int n, start, end, len; n = pic_get_args(pic, "b|ii", &from, &start, &end); + buf = pic_blob(pic, from, &len); + switch (n) { case 1: start = 0; case 2: - end = from->len; + end = len; } - if (end < start) { - pic_errorf(pic, "make-bytevector: end index must not be less than start index"); - } + VALID_RANGE(pic, len, start, end); - to = pic_blob_value(pic, 0, end - start); - while (start < end) { - to->data[i++] = from->data[start++]; - } - - return pic_obj_value(to); + return pic_blob_value(pic, buf + start, end - start); } static pic_value pic_blob_bytevector_append(pic_state *pic) { - int argc, i, j, len; - pic_value *argv; - struct pic_blob *blob; + int argc, i, l, len; + unsigned char *buf, *dst; + pic_value *argv, blob; pic_get_args(pic, "*", &argc, &argv); len = 0; for (i = 0; i < argc; ++i) { pic_assert_type(pic, argv[i], blob); - len += pic_blob_ptr(argv[i])->len; + pic_blob(pic, argv[i], &l); + len += l; } - blob = pic_blob_value(pic, 0, len); + blob = pic_blob_value(pic, NULL, len); + dst = pic_blob(pic, blob, NULL); len = 0; for (i = 0; i < argc; ++i) { - for (j = 0; j < pic_blob_ptr(argv[i])->len; ++j) { - blob->data[len + j] = pic_blob_ptr(argv[i])->data[j]; - } - len += pic_blob_ptr(argv[i])->len; + buf = pic_blob(pic, argv[i], &l); + memcpy(dst + len, buf, l); + len += l; } - return pic_obj_value(blob); + return blob; } static pic_value pic_blob_list_to_bytevector(pic_state *pic) { - struct pic_blob *blob; + pic_value blob; unsigned char *data; pic_value list, e, it; @@ -215,7 +225,7 @@ pic_blob_list_to_bytevector(pic_state *pic) blob = pic_blob_value(pic, 0, pic_length(pic, list)); - data = blob->data; + data = pic_blob(pic, blob, NULL); pic_for_each (e, list, it) { pic_assert_type(pic, e, int); @@ -225,29 +235,32 @@ pic_blob_list_to_bytevector(pic_state *pic) *data++ = (unsigned char)pic_int(pic, e); } - return pic_obj_value(blob); + return blob; } static pic_value pic_blob_bytevector_to_list(pic_state *pic) { - struct pic_blob *blob; - pic_value list; - int n, start, end, i; + pic_value blob, list; + unsigned char *buf; + int n, len, start, end, i; n = pic_get_args(pic, "b|ii", &blob, &start, &end); + buf = pic_blob(pic, blob, &len); + switch (n) { case 1: start = 0; case 2: - end = blob->len; + end = len; } - list = pic_nil_value(pic); + VALID_RANGE(pic, len, start, end); + list = pic_nil_value(pic); for (i = start; i < end; ++i) { - pic_push(pic, pic_int_value(pic, blob->data[i]), list); + pic_push(pic, pic_int_value(pic, buf[i]), list); } return pic_reverse(pic, list); } diff --git a/extlib/benz/bool.c b/extlib/benz/bool.c index c5d47823..3e474e55 100644 --- a/extlib/benz/bool.c +++ b/extlib/benz/bool.c @@ -109,18 +109,17 @@ internal_equal_p(pic_state *pic, pic_value x, pic_value y, int depth, khash_t(m) return pic_str_cmp(pic, pic_str_ptr(x), pic_str_ptr(y)) == 0; } case PIC_TYPE_BLOB: { - struct pic_blob *blob1, *blob2; - int i; + int xlen, ylen; + const unsigned char *xbuf, *ybuf; - blob1 = pic_blob_ptr(x); - blob2 = pic_blob_ptr(y); + xbuf = pic_blob(pic, x, &xlen); + ybuf = pic_blob(pic, y, &ylen); - if (blob1->len != blob2->len) { + if (xlen != ylen) { return false; } - for (i = 0; i < blob1->len; ++i) { - if (blob1->data[i] != blob2->data[i]) - return false; + if (memcmp(xbuf, ybuf, xlen) != 0) { + return false; } return true; } diff --git a/extlib/benz/include/picrin.h b/extlib/benz/include/picrin.h index 84df7381..9e796dc3 100644 --- a/extlib/benz/include/picrin.h +++ b/extlib/benz/include/picrin.h @@ -54,7 +54,6 @@ typedef struct { struct pic_object; struct pic_symbol; struct pic_string; -struct pic_blob; struct pic_proc; struct pic_port; struct pic_error; @@ -120,13 +119,13 @@ pic_value pic_vcall(pic_state *, struct pic_proc *proc, int, va_list); pic_value pic_apply(pic_state *, struct pic_proc *proc, int n, pic_value *argv); pic_value pic_applyk(pic_state *, struct pic_proc *proc, int n, pic_value *argv); -PIC_INLINE int pic_int(pic_state *, pic_value); -PIC_INLINE double pic_float(pic_state *, pic_value); -PIC_INLINE char pic_char(pic_state *, pic_value); -#define pic_bool(pic,v) (! pic_false_p(pic, v)) +PIC_INLINE int pic_int(pic_state *, pic_value i); +PIC_INLINE double pic_float(pic_state *, pic_value f); +PIC_INLINE char pic_char(pic_state *, pic_value c); +#define pic_bool(pic,b) (! pic_false_p(pic, b)) const char *pic_str(pic_state *, struct pic_string *); -unsigned char *pic_blob(pic_state *, struct pic_blob *, int *len); -void *pic_data(pic_state *, pic_value); +unsigned char *pic_blob(pic_state *, pic_value blob, int *len); +void *pic_data(pic_state *, pic_value str); typedef struct { const char *type_name; @@ -147,7 +146,7 @@ struct pic_string *pic_str_value(pic_state *, const char *str, int len); #define pic_lit_value(pic, lit) pic_str_value(pic, "" lit, -((int)sizeof lit - 1)) struct pic_string *pic_strf_value(pic_state *, const char *fmt, ...); struct pic_string *pic_vstrf_value(pic_state *, const char *fmt, va_list ap); -struct pic_blob *pic_blob_value(pic_state *, const unsigned char *buf, int len); +pic_value pic_blob_value(pic_state *, const unsigned char *buf, int len); struct pic_data *pic_data_value(pic_state *, void *ptr, const pic_data_type *type); enum { diff --git a/extlib/benz/include/picrin/compat.h b/extlib/benz/include/picrin/compat.h index ba4d964e..e367a6ce 100644 --- a/extlib/benz/include/picrin/compat.h +++ b/extlib/benz/include/picrin/compat.h @@ -221,6 +221,18 @@ memmove(void *dst, const void *src, size_t n) return d; } +PIC_INLINE int +memcmp(const void *b1, const void *b2, size_t n) +{ + const char *s1 = b1, *s2 = b2; + + while (*s1 == *s2 && n-- > 0) { + s1++; + s2++; + } + return (unsigned)*s1 - (unsigned)*s2; +} + PIC_INLINE char * strcpy(char *dst, const char *src) { diff --git a/extlib/benz/include/picrin/object.h b/extlib/benz/include/picrin/object.h index 7e71ef38..ff3cb20d 100644 --- a/extlib/benz/include/picrin/object.h +++ b/extlib/benz/include/picrin/object.h @@ -121,11 +121,11 @@ struct pic_port { }; #define pic_pair_ptr(pic, o) ((struct pic_pair *)pic_obj_ptr(o)) +#define pic_blob_ptr(pic, v) ((struct pic_blob *)pic_obj_ptr(v)) #define pic_vec_ptr(pic, o) ((struct pic_vector *)pic_obj_ptr(o)) #define pic_dict_ptr(pic, v) ((struct pic_dict *)pic_obj_ptr(v)) #define pic_sym_ptr(v) ((pic_sym *)pic_obj_ptr(v)) #define pic_id_ptr(v) ((pic_id *)pic_obj_ptr(v)) -#define pic_blob_ptr(v) ((struct pic_blob *)pic_obj_ptr(v)) #define pic_str_ptr(o) ((struct pic_string *)pic_obj_ptr(o)) #define pic_weak_ptr(v) ((struct pic_weak *)pic_obj_ptr(v)) #define pic_data_ptr(o) ((struct pic_data *)pic_obj_ptr(o)) diff --git a/extlib/benz/port.c b/extlib/benz/port.c index 136de293..039dbf91 100644 --- a/extlib/benz/port.c +++ b/extlib/benz/port.c @@ -125,14 +125,15 @@ pic_port_close_port(pic_state *pic) static pic_value pic_port_open_input_bytevector(pic_state *pic) { - struct pic_blob *blob; - xFILE *file; + pic_value blob; + unsigned char *buf; + int len; pic_get_args(pic, "b", &blob); - file = xfopen_buf(pic, (const char *)blob->data, blob->len, "r"); + buf = pic_blob(pic, blob, &len); - return pic_obj_value(pic_make_port(pic, file)); + return pic_obj_value(pic_make_port(pic, xfopen_buf(pic, (char *)buf, len, "r"))); } static pic_value @@ -157,7 +158,7 @@ pic_port_get_output_bytevector(pic_state *pic) if (xfget_buf(pic, port->file, &buf, &len) < 0) { pic_errorf(pic, "port was not created by open-output-bytevector"); } - return pic_obj_value(pic_blob_value(pic, (unsigned char *)buf, len)); + return pic_blob_value(pic, (unsigned char *)buf, len); } static pic_value @@ -211,63 +212,51 @@ static pic_value pic_port_read_bytevector(pic_state *pic) { struct pic_port *port = pic_stdin(pic); - struct pic_blob *blob; + unsigned char *buf; int k, i; pic_get_args(pic, "i|p", &k, &port); assert_port_profile(port, X_READ, "read-bytevector"); - blob = pic_blob_value(pic, 0, k); + buf = pic_blob(pic, pic_blob_value(pic, NULL, k), NULL); - i = xfread(pic, blob->data, sizeof(char), k, port->file); + i = xfread(pic, buf, sizeof(char), k, port->file); if (i == 0) { return pic_eof_object(pic); } - else { - pic_realloc(pic, blob->data, i); - blob->len = i; - return pic_obj_value(blob); - } + return pic_blob_value(pic, buf, i); } static pic_value pic_port_read_bytevector_ip(pic_state *pic) { struct pic_port *port; - struct pic_blob *bv; - char *buf; + pic_value bv; + unsigned char *buf; int n, start, end, i, len; n = pic_get_args(pic, "b|pii", &bv, &port, &start, &end); + + buf = pic_blob(pic, bv, &len); + switch (n) { case 1: port = pic_stdin(pic); case 2: start = 0; case 3: - end = bv->len; + end = len; } + VALID_RANGE(pic, len, start, end); assert_port_profile(port, X_READ, "read-bytevector!"); - if (end < start) { - pic_errorf(pic, "read-bytevector!: end index must be greater than or equal to start index"); - } - - len = end - start; - - buf = pic_calloc(pic, len, sizeof(char)); - i = xfread(pic, buf, sizeof(char), len, port->file); - memcpy(bv->data + start, buf, i); - pic_free(pic, buf); - + i = xfread(pic, buf + start, 1, end - start, port->file); if (i == 0) { return pic_eof_object(pic); } - else { - return pic_int_value(pic, i); - } + return pic_int_value(pic, i); } static pic_value @@ -287,24 +276,31 @@ pic_port_write_u8(pic_state *pic) static pic_value pic_port_write_bytevector(pic_state *pic) { - struct pic_blob *blob; + pic_value blob; struct pic_port *port; - int n, start, end, i; + unsigned char *buf; + int n, start, end, len, done; n = pic_get_args(pic, "b|pii", &blob, &port, &start, &end); + + buf = pic_blob(pic, blob, &len); + switch (n) { case 1: port = pic_stdout(pic); case 2: start = 0; case 3: - end = blob->len; + end = len; } + VALID_RANGE(pic, len, start, end); assert_port_profile(port, X_WRITE, "write-bytevector"); - for (i = start; i < end; ++i) { - xfputc(pic, blob->data[i], port->file); + done = 0; + while (done < end - start) { + done += xfwrite(pic, buf + start + done, 1, end - start - done, port->file); + /* FIXME: error check... */ } return pic_undef_value(pic); } diff --git a/extlib/benz/proc.c b/extlib/benz/proc.c index 712c26db..017d691f 100644 --- a/extlib/benz/proc.c +++ b/extlib/benz/proc.c @@ -23,7 +23,7 @@ * m pic_sym ** symbol * v pic_value * vector object * s struct pic_str ** string object - * b struct pic_blob ** bytevector object + * b pic_value * bytevector object * l struct pic_proc ** lambda object * p struct pic_port ** port object * d pic_value * dictionary object @@ -149,7 +149,6 @@ pic_get_args(pic_state *pic, const char *format, ...) PTR_CASE('m', sym, pic_sym *) PTR_CASE('s', str, struct pic_string *) - PTR_CASE('b', blob, struct pic_blob *) PTR_CASE('l', proc, struct pic_proc *) PTR_CASE('p', port, struct pic_port *) PTR_CASE('e', error, struct pic_error *) @@ -157,6 +156,7 @@ pic_get_args(pic_state *pic, const char *format, ...) #define OBJ_CASE(c, type) VAL_CASE(c, type, pic_value, v) + OBJ_CASE('b', blob) OBJ_CASE('v', vec) OBJ_CASE('d', dict) diff --git a/extlib/benz/read.c b/extlib/benz/read.c index 4f26f86f..3cefa8a3 100644 --- a/extlib/benz/read.c +++ b/extlib/benz/read.c @@ -499,7 +499,7 @@ read_blob(pic_state *pic, xFILE *file, int c) int nbits, n; int len; unsigned char *dat; - struct pic_blob *blob; + pic_value blob; nbits = 0; @@ -532,7 +532,7 @@ read_blob(pic_state *pic, xFILE *file, int c) blob = pic_blob_value(pic, dat, len); pic_free(pic, dat); - return pic_obj_value(blob); + return blob; } static pic_value diff --git a/extlib/benz/write.c b/extlib/benz/write.c index 228bc3d9..f5f8ceb6 100644 --- a/extlib/benz/write.c +++ b/extlib/benz/write.c @@ -48,14 +48,17 @@ writer_control_destroy(struct writer_control *p) } static void -write_blob(pic_state *pic, struct pic_blob *blob, xFILE *file) +write_blob(pic_state *pic, pic_value blob, xFILE *file) { - int i; + const unsigned char *buf; + int len, i; + + buf = pic_blob(pic, blob, &len); xfprintf(pic, file, "#u8("); - for (i = 0; i < blob->len; ++i) { - xfprintf(pic, file, "%d", blob->data[i]); - if (i + 1 < blob->len) { + for (i = 0; i < len; ++i) { + xfprintf(pic, file, "%d", buf[i]); + if (i + 1 < len) { xfprintf(pic, file, " "); } } @@ -303,7 +306,7 @@ write_core(struct writer_control *p, pic_value obj) xfprintf(pic, file, "%s", pic_str(pic, pic_sym_name(pic, pic_sym_ptr(obj)))); break; case PIC_TYPE_BLOB: - write_blob(pic, pic_blob_ptr(obj), file); + write_blob(pic, obj, file); break; case PIC_TYPE_CHAR: write_char(pic, pic_char(pic, obj), file, p->mode);