ref: bc6da35e59c59afc599e67ec45b9f67cfcdeca84
parent: 20a9d526576724d465dd0f55dcb60677fb37a79a
author: Tor Andersson <tor@ccxvii.net>
date: Thu Feb 6 13:19:07 EST 2014
Add decode/encode URI functions.
--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -66,6 +66,111 @@
return 1;
}
+static int Encode(js_State *J, const char *str, const char *unescaped)
+{
+ struct sbuffer *sb = NULL;
+
+ static const char *HEX = "0123456789ABCDEF";
+
+ while (*str) {
+ int c = (unsigned char) *str++;
+ if (strchr(unescaped, c))
+ sb = sb_putc(sb, c);
+ else {
+ sb = sb_putc(sb, '%');
+ sb = sb_putc(sb, HEX[(c >> 4) & 0xf]);
+ sb = sb_putc(sb, HEX[c & 0xf]);
+ }
+ }
+ sb = sb_putc(sb, 0);
+
+ if (js_try(J)) {
+ free(sb);
+ js_throw(J);
+ }
+ js_pushstring(J, sb ? sb->s : "");
+ js_endtry(J);
+ free(sb);
+ return 1;
+}
+
+static inline int ishex(int c)
+{
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+}
+
+static inline int tohex(int c)
+{
+ if (c >= '0' && c <= '9') return c - '0';
+ if (c >= 'a' && c <= 'f') return c - 'a' + 0xA;
+ if (c >= 'A' && c <= 'F') return c - 'A' + 0xA;
+ return 0;
+}
+
+static int Decode(js_State *J, const char *str, const char *reserved)
+{
+ struct sbuffer *sb = NULL;
+ int a, b;
+
+ while (*str) {
+ int c = (unsigned char) *str++;
+ if (c != '%')
+ sb = sb_putc(sb, c);
+ else {
+ if (!str[0] || !str[1])
+ js_urierror(J, "truncated escape sequence");
+ a = *str++;
+ b = *str++;
+ if (!ishex(a) || !ishex(b))
+ js_urierror(J, "invalid escape sequence");
+ c = tohex(a) << 4 | tohex(b);
+ if (!strchr(reserved, c))
+ sb = sb_putc(sb, c);
+ else {
+ sb = sb_putc(sb, '%');
+ sb = sb_putc(sb, a);
+ sb = sb_putc(sb, b);
+ }
+ }
+ }
+ sb = sb_putc(sb, 0);
+
+ if (js_try(J)) {
+ free(sb);
+ js_throw(J);
+ }
+ js_pushstring(J, sb ? sb->s : "");
+ js_endtry(J);
+ free(sb);
+ return 1;
+}
+
+#define URIRESERVED ";/?:@&=+$,"
+#define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define URIDIGIT "0123456789"
+#define URIMARK "-_.!~*`()"
+#define URIUNESCAPED URIALPHA URIDIGIT URIMARK
+
+static int jsB_decodeURI(js_State *J, int argc)
+{
+ return Decode(J, js_tostring(J, 1), URIRESERVED "#");
+}
+
+static int jsB_decodeURIComponent(js_State *J, int argc)
+{
+ return Decode(J, js_tostring(J, 1), "");
+}
+
+static int jsB_encodeURI(js_State *J, int argc)
+{
+ return Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
+}
+
+static int jsB_encodeURIComponent(js_State *J, int argc)
+{
+ return Encode(J, js_tostring(J, 1), URIUNESCAPED);
+}
+
void jsB_init(js_State *J)
{
/* Create the prototype objects here, before the constructors */
@@ -114,4 +219,9 @@
jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
jsB_globalf(J, "isNaN", jsB_isNaN, 1);
jsB_globalf(J, "isFinite", jsB_isFinite, 1);
+
+ jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
+ jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
+ jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
+ jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
}
--- a/jsbuiltin.h
+++ b/jsbuiltin.h
@@ -17,4 +17,33 @@
void jsB_propn(js_State *J, const char *name, double number);
void jsB_props(js_State *J, const char *name, const char *string);
+struct sbuffer { int n, m; char s[64]; };
+
+static struct sbuffer *sb_putc(struct sbuffer *sb, int c)
+{
+ if (!sb) {
+ sb = malloc(sizeof *sb);
+ sb->n = 0;
+ sb->m = sizeof sb->s;
+ } else if (sb->n == sb->m) {
+ sb = realloc(sb, (sb->m *= 2) + offsetof(struct sbuffer, s));
+ }
+ sb->s[sb->n++] = c;
+ return sb;
+}
+
+static inline struct sbuffer *sb_puts(struct sbuffer *sb, const char *s)
+{
+ while (*s)
+ sb = sb_putc(sb, *s++);
+ return sb;
+}
+
+static inline struct sbuffer *sb_putm(struct sbuffer *sb, const char *s, const char *e)
+{
+ while (s < e)
+ sb = sb_putc(sb, *s++);
+ return sb;
+}
+
#endif
--- a/jsstring.c
+++ b/jsstring.c
@@ -7,35 +7,6 @@
#define nelem(a) (sizeof (a) / sizeof (a)[0])
-struct sbuffer { int n, m; char s[64]; };
-
-static struct sbuffer *sb_putc(struct sbuffer *sb, int c)
-{
- if (!sb) {
- sb = malloc(sizeof *sb);
- sb->n = 0;
- sb->m = sizeof sb->s;
- } else if (sb->n == sb->m) {
- sb = realloc(sb, (sb->m *= 2) + offsetof(struct sbuffer, s));
- }
- sb->s[sb->n++] = c;
- return sb;
-}
-
-static struct sbuffer *sb_puts(struct sbuffer *sb, const char *s)
-{
- while (*s)
- sb = sb_putc(sb, *s++);
- return sb;
-}
-
-static struct sbuffer *sb_putm(struct sbuffer *sb, const char *s, const char *e)
-{
- while (s < e)
- sb = sb_putc(sb, *s++);
- return sb;
-}
-
static int jsB_new_String(js_State *J, int argc)
{
js_newstring(J, argc > 0 ? js_tostring(J, 1) : "");