scmno****@osdn*****
scmno****@osdn*****
Thu Jan 11 05:15:25 JST 2018
changeset f044f8e82b4d in quipu/quipu details: http://hg.osdn.jp/view/quipu/quipu?cmd=changeset;node=f044f8e82b4d user: Agustina Arzille <avarz****@riseu*****> date: Wed Jan 10 17:15:08 2018 -0300 description: First functionality needed for string interpolation diffstat: io.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ io.h | 2 + str.cpp | 2 +- str.h | 5 +- 4 files changed, 142 insertions(+), 2 deletions(-) diffs (190 lines): diff -r 96f86e4d129f -r f044f8e82b4d io.cpp --- a/io.cpp Wed Jan 10 04:11:35 2018 +0000 +++ b/io.cpp Wed Jan 10 17:15:08 2018 -0300 @@ -1110,5 +1110,140 @@ return (interp->retval); } +// String interpolation. + +static int +read_fail (interpreter *, stream&, char *, uint32_t) +{ + return (0); +} + +static object +read_from_cstr (interpreter *interp, const void *s, int len) +{ + stream instrm; + bvector bv; + + bv.type = typecode::BVECTOR; + bv.nbytes = len; + + instrm.rdbuf.init ((char *)s, len); + instrm.cookie = 0, instrm.ilock = UNBOUND; + instrm.bvec = bv.as_obj (); + + instrm.type = typecode::STREAM; + instrm.pos = intobj (0); + instrm.flags = STRM_UTF8 | STRM_READ; + + stream::xops ops; + ops.read = read_fail; + + instrm.ops = ops; + + return (read_sexpr (interp, instrm.as_obj ())); +} + +static inline +const char* xmemchr (const void *p, int ch, size_t len) +{ + return ((const char *)memchr (p, ch, len)); +} + +static bool +sanitize_fmt (const char *p1, const char *p2) +{ + for (; p1 != p2; ++p1) + if (!isdigit (*p1) && *p1 != '.' && *p1 != '$') + return (false); + + return (true); +} + +object expand_str (interpreter *interp, object str) +{ + string *sp = as_str (str); + const char *start = (const char *)sp->data; + int nb = sp->nbytes; + const char *ptr = xmemchr (start, '%', nb); + + if (!ptr) + qp_return (str); + + stream *ns = strstream (interp, alloc_str (interp, 0), STRM_WRITE); + ns->write (interp, start, ptr - start); + + interp->push (ns->as_obj ()); + + stackref args (interp, NIL); + object *tailp = &*args; + + while (true) + { + if (ptr[1] == '%') + { + ns->nputb (interp, 2, '%'); + const char *tp = xmemchr (ptr += 2, '%', nb -= 2); + if (!tp) + { + ns->write (interp, ptr, sp->nbytes - (ptr - start)); + break; + } + + ns->write (interp, ptr, tp - ptr); + nb -= tp - ptr, ptr = tp; + continue; + } + + const char *p1 = xmemchr (ptr + 1, '{', ptr - start - 1); + + if (!p1) + interp->raise2 ("arg-error", "invalid format string " + "(expected '{' after '%')"); + + nb = sp->nbytes - (int)(p1 - start); + const char *p2 = xmemchr (p1 + 1, '}', nb - 1); + + if (!p2) + interp->raise2 ("arg-error", "invalid format string " + "(unbalanced '{}' specifiers"); + + object arg = read_from_cstr (interp, p1 + 1, p2 - p1); + *tailp = cons::make (interp, arg, *tailp); + tailp = &xcdr(*tailp); + + if (!sanitize_fmt (ptr + 1, p1)) + { + static const char ERR[] = "invalid format string: got "; + char buf[sizeof (ERR) * 2]; + memcpy (buf, ERR, sizeof (ERR) - 1); + nb = min (sizeof (buf) - sizeof (ERR) - 1, (size_t)(p1 - ptr) - 1); + memcpy (buf + sizeof (ERR) - 1, ptr + 1, nb); + interp->raise2 ("arg-error", buf); + } + + ns->write (interp, ptr, p1 - ptr); + ns->putb (interp, 'Q'); + ptr = p2 + 1; + + nb = sp->nbytes - (ptr - start); + ptr = xmemchr (ptr, '%', nb); + if (!ptr) + { + ns->write (interp, p2 + 1, nb); + break; + } + + ns->write (interp, p2 + 1, ptr - p2 - 1); + } + + if (*args == NIL) + // Simple string. + return (sstream_get (interp, ns)); + + *args = cons::make (interp, sstream_get (interp, ns), *args); + *args = cons::make (interp, intern (interp, "%fmt-str"), *args); + qp_return (*args); +} + QP_DECLS_END diff -r 96f86e4d129f -r f044f8e82b4d io.h --- a/io.h Wed Jan 10 04:11:35 2018 +0000 +++ b/io.h Wed Jan 10 17:15:08 2018 -0300 @@ -11,6 +11,8 @@ QP_EXPORT int xwrite (interpreter *__interp, stream *__strm, object __obj, uint32_t *__lkcnt = 0); +QP_EXPORT object expand_str (interpreter *__interp, object __str); + QP_DECLS_END #endif diff -r 96f86e4d129f -r f044f8e82b4d str.cpp --- a/str.cpp Wed Jan 10 04:11:35 2018 +0000 +++ b/str.cpp Wed Jan 10 17:15:08 2018 -0300 @@ -327,7 +327,7 @@ // Make up the string from the accumulated bytes. sstream_data *dp = (sstream_data *)strm->cookie; - return (string::make (interp, (const char *)dp->datap, dp->nbytes)); + qp_return (string::make (interp, (const char *)dp->datap, dp->nbytes)); } int write_s (interpreter *interp, stream *strm, object obj) diff -r 96f86e4d129f -r f044f8e82b4d str.h --- a/str.h Wed Jan 10 04:11:35 2018 +0000 +++ b/str.h Wed Jan 10 17:15:08 2018 -0300 @@ -19,7 +19,7 @@ static string* alloc_raw (uint32_t __nb); }; -/* Max value for a character (as a UTF-32 codepoint). */ +// Max value for a character (as a UTF-32 codepoint). const uint32_t MAX_CHAR = 0x110000; #ifdef QP_ARCH_WIDE @@ -139,6 +139,9 @@ QP_EXPORT object sstream_get (interpreter *__interp, stream *__strm); +QP_EXPORT object p_fmt_str (interpreter *__interp, + object *__argv, int __argc); + QP_EXPORT const char* chobj_repr (uint32_t __ch); QP_DECLS_END