ref: 0b7b8cf380ced404a763a81e86db439ee4915393
parent: a61a1f51567f27ec605986354a28f8360abb1bda
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Sep 8 19:08:12 EDT 2016
Add url escaping.
--- a/lib/escfmt/bld.sub
+++ b/lib/escfmt/bld.sub
@@ -1,7 +1,8 @@
lib escfmt =
escsh.myr
eschtml.myr
+ escurl.myr
lib ../std:std
- lib ../sys:sys
+ lib ../sys:sys
;;
--- /dev/null
+++ b/lib/escfmt/escurl.myr
@@ -1,0 +1,52 @@
+use std
+
+pkg escfmt =
+ type escurl = byte[:]
+
+ const url : (s : byte[:] -> escurl)
+;;
+
+const __init__ = {
+ var s = ("" : escurl)
+ std.fmtinstall(std.typeof(s), urlfmt, [][:])
+}
+
+const url = {s
+ -> (s : escurl)
+}
+
+const urlfmt = {sb, ap, args
+ var s : byte[:]
+
+ s = std.vanext(ap)
+ for b in s
+ match (b : char)
+ | ':': std.sbfmt(sb, "%{x}", b)
+ | '/': std.sbfmt(sb, "%{x}", b)
+ | '?': std.sbfmt(sb, "%{x}", b)
+ | '#': std.sbfmt(sb, "%{x}", b)
+ | '[': std.sbfmt(sb, "%{x}", b)
+ | ']': std.sbfmt(sb, "%{x}", b)
+ | '@': std.sbfmt(sb, "%{x}", b)
+ | '!': std.sbfmt(sb, "%{x}", b)
+ | '$': std.sbfmt(sb, "%{x}", b)
+ | '&': std.sbfmt(sb, "%{x}", b)
+ | '\'': std.sbfmt(sb, "%{x}", b)
+ | '(': std.sbfmt(sb, "%{x}", b)
+ | ')': std.sbfmt(sb, "%{x}", b)
+ | '*': std.sbfmt(sb, "%{x}", b)
+ | '+': std.sbfmt(sb, "%{x}", b)
+ | ',': std.sbfmt(sb, "%{x}", b)
+ | ';': std.sbfmt(sb, "%{x}", b)
+ | '=': std.sbfmt(sb, "%{x}", b)
+ | '%': std.sbfmt(sb, "%{x}", b)
+ | c:
+ if b >= 0x80
+ std.sbfmt(sb, "%{x}", b)
+ else
+ std.sbfmt(sb, "{}", c)
+ ;;
+
+ ;;
+ ;;
+}
--- /dev/null
+++ b/lib/escfmt/test/escurl.myr
@@ -1,0 +1,28 @@
+use std
+use escfmt
+use testr
+
+const main = {
+ testr.run([\
+ [.name="unchanged", .fn={ctx
+ var s = std.fmt("{}", escfmt.url("word"))
+ testr.check(ctx, std.sleq("word", s), std.fmt("mismatched escape {}", s))
+ std.slfree(s)
+ }],
+ [.name="allspecials", .fn={ctx
+ var s = std.fmt("{}", escfmt.url(":/?#[]@!$&'()*+,;=%"))
+ testr.check(ctx, \
+ std.sleq("%3a%2f%3f%23%5b%5d%40%21%24%26%27%28%29%2a%2b%2c%3b%3d%25", s), \
+ std.fmt("mismatched escape {}", s))
+ std.slfree(s)
+ }],
+ [.name="unicodes", .fn={ctx
+ var s = std.fmt("{}", escfmt.url("᚛᚛ᚉᚑᚅᚔᚉᚉᚔ"))
+ testr.check(ctx, \
+ std.sleq("%e1%9a%9b%e1%9a%9b%e1%9a%89%e1%9a%91%e1%9a%85%e1%9a%94%e1%9a%89%e1%9a%89%e1%9a%94", s), \
+ std.fmt("mismatched escape {}", s))
+ std.slfree(s)
+ }],
+ ][:])
+}
+