klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 4f47f6e74de8f5d6957f855727b66767cc672442
parent e75fed6da1649fa472cce34f6e36634de0d75bab
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Wed, 23 Mar 2011 03:04:56 -0300

Added string-append to the ground environment.

Diffstat:
Msrc/kground.c | 2+-
Msrc/kgstrings.c | 55++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/kgstrings.h | 6+++++-
3 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/src/kground.c b/src/kground.c @@ -614,7 +614,7 @@ void kinit_ground_env(klisp_State *K) add_applicative(K, ground_env, "substring", substring, 0); /* 13.2.6? string-append */ - /* TODO */ + add_applicative(K, ground_env, "string-append", string_append, 0); /* 13.2.7? string->list, list->string */ add_applicative(K, ground_env, "string->list", string_to_list, 0); diff --git a/src/kgstrings.c b/src/kgstrings.c @@ -182,7 +182,54 @@ void substring(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) } /* 13.2.6? string-append */ -/* TODO */ +/* TEMP: this does 3 passes over the list */ +void string_append(klisp_State *K, TValue *xparams, TValue ptree, + TValue denv) +{ + UNUSED(xparams); + UNUSED(denv); + int32_t dummy; + /* don't allow cycles */ + int32_t pairs = check_typed_list(K, "string-append", "string", kstringp, + false, ptree, &dummy); + + TValue new_str; + int64_t total_size = 0; /* use int64 to check for overflow */ + /* the if isn't strictly necessary but it's clearer this way */ + int32_t saved_pairs = pairs; /* save pairs for next loop */ + TValue tail = ptree; + while(pairs--) { + total_size += kstring_size(kcar(tail)); + if (total_size > INT32_MAX) { + klispE_throw(K, "string-append: resulting string is too big"); + return; + } + tail = kcdr(tail); + } + /* this is safe */ + int32_t size = (int32_t) total_size; + + if (size == 0) { + new_str = K->empty_string; + } else { + new_str = kstring_new_g(K, size); + char *buf = kstring_buf(new_str); + /* loop again to copy the chars of each string */ + tail = ptree; + pairs = saved_pairs; + + while(pairs--) { + TValue first = kcar(tail); + int32_t first_size = kstring_size(first); + memcpy(buf, kstring_buf(first), first_size); + buf += first_size; + tail = kcdr(tail); + } + } + + kapply_cc(K, new_str); +} + /* 13.2.7? string->list, list->string */ void string_to_list(klisp_State *K, TValue *xparams, TValue ptree, @@ -265,3 +312,9 @@ void string_fillS(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) again must be equal? which happens here */ /* TODO */ + +/* Helpers */ +bool kstringp(TValue obj) +{ + return ttisstring(obj); +} diff --git a/src/kgstrings.h b/src/kgstrings.h @@ -50,7 +50,8 @@ void string(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); void substring(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); /* 13.2.6? string-append */ -/* TODO */ +void string_append(klisp_State *K, TValue *xparams, TValue ptree, + TValue denv); /* 13.2.7? string->list, list->string */ void list_to_string(klisp_State *K, TValue *xparams, TValue ptree, @@ -81,4 +82,7 @@ void string_fillS(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); */ /* TODO */ +/* Helpers */ +bool kstringp(TValue obj); + #endif