ref: 5d669c823851eb8c74acba4b0e8673f8da02ae0a
parent: f536dec7915b6285916c7281ac992c24fa1ccf32
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Sep 8 17:36:33 EDT 2016
Add start of general string escaping library.
--- a/lib/bld.sub
+++ b/lib/bld.sub
@@ -2,6 +2,7 @@
bio
date
cryptohash
+ escfmt
inifile
fileutil
regex
--- /dev/null
+++ b/lib/escfmt/bld.sub
@@ -1,0 +1,6 @@
+lib escfmt =
+ escsh.myr
+
+ lib ../std:std
+ lib ../sys:sys
+;;
--- /dev/null
+++ b/lib/escfmt/escsh.myr
@@ -1,0 +1,31 @@
+use std
+
+pkg escfmt =
+ type escsh = byte[:]
+
+ const sh : (s : byte[:] -> escsh)
+;;
+
+const __init__ = {
+ var s = ("" : escsh)
+ std.fmtinstall(std.typeof(s), shfmt, [][:])
+}
+
+const sh = {s
+ -> (s : escsh)
+}
+
+const shfmt = {sb, ap, args
+ var s : byte[:]
+
+ s = std.vanext(ap)
+ std.sbputb(sb, ('\'' : byte))
+ for b in s
+ if b == ('\'' : byte)
+ std.sbputs(sb, "'\\''")
+ else
+ std.sbputb(sb, b)
+ ;;
+ ;;
+ std.sbputb(sb, ('\'' : byte))
+}
--- /dev/null
+++ b/lib/escfmt/test/escsh.myr
@@ -1,0 +1,29 @@
+use std
+use escfmt
+use testr
+
+const main = {
+ testr.run([\
+ [.name="basic", .fn={ctx
+ var s = std.fmt("{}", escfmt.sh("word"))
+ testr.check(ctx, std.sleq("'word'", s), "mismatched escape")
+ std.slfree(s)
+ }],
+ [.name="twowords", .fn={ctx
+ var s = std.fmt("{}", escfmt.sh("two words"))
+ testr.check(ctx, std.sleq("'two words'", s), "mismatched escape")
+ std.slfree(s)
+ }],
+ [.name="simplequote", .fn={ctx
+ var s = std.fmt("{}", escfmt.sh("two'words"))
+ testr.check(ctx, std.sleq("'two'\\''words'", s), "mismatched escape")
+ std.slfree(s)
+ }],
+ [.name="quotequote", .fn={ctx
+ var s = std.fmt("{}", escfmt.sh("two'\\''words"))
+ testr.check(ctx, std.sleq("'two'\\''\\'\\'''\\''words'", s), "mismatched escape")
+ std.slfree(s)
+ }]
+ ][:])
+}
+