ref: 38c0cf0737de03906729054ad7b7b011dd1ca475
dir: /appl/lib/ecmascript/uri.b/
tohex(c: int): int { if(c > 9) return c-10+'A'; return c+'0'; } fromhex(ex: ref Exec, c1: int, c2: int): int { c1 = hexdigit(c1); c2 = hexdigit(c2); if(c1 < 0 || c2 < 0) runtime(ex, URIError, "bad hex digit"); return 16*c1+c2; } isres(c: int): int { return c == ';' || c == '/' || c == '?' || c == ':' || c == '@' || c == '&' || c == '=' || c == '+' || c == '$' || c == ',' || c == '#'; # add '#' here for convenience } isunesc(c: int): int { return isalpha(c) || isdigit(c) || c == '-' || c == '_' || c == '.' || c == '!' || c == '~' || c == '*' || c == ''' || c == '(' || c == ')'; } encode(ex: ref Exec, s: string, flag: int): string { m := len s; r := ""; n := len r; for(k := 0; k < m; k++){ c := s[k]; if(isunesc(c) || (flag && isres(c))) r[n++] = c; else{ if(c >= 16rdc00 && c <= 16rdfff) runtime(ex, URIError, "char out of range"); if(c < 16rd800 || c > 16rdbff) ; else{ if(++k == m) runtime(ex, URIError, "char missing"); if(s[k] < 16rdc00 || s[k] > 16rdfff) runtime(ex, URIError, "char out of range"); c = (c-16rd800)*16r400 + (s[k]-16rdc00) + 16r10000; } s1 := "Z"; s1[0] = c; o := array of byte s1; for(j := 0; j < len o; j++){ r += sys->sprint("%%%c%c", tohex(int o[j]/16), tohex(int o[j]%16)); n += 3; } } } return r; } decode(ex: ref Exec, s: string, flag: int): string { m := len s; r := ""; n := len r; for(k := 0; k < m; k++){ c := s[k]; if(c != '%') r[n++] = c; else{ start := k; if(k+2 >= m) runtime(ex, URIError, "char missing"); c = fromhex(ex, s[k+1], s[k+2]); k += 2; if((c&16r80 == 0)){ if(flag && isres(c)){ r += s[start: k+1]; n += k+1-start; } else r[n++] = c; } else{ for(i := 1; ((c<<i)&16r80) == 0; i++) ; if(i == 1 || i > 4) runtime(ex, URIError, "bad hex number"); o := array[i] of byte; o[0] = byte c; if(k+3*(n-1) >= m) runtime(ex, URIError, "char missing"); for(j := 1; j < i; j++){ if(s[++k] != '%') runtime(ex, URIError, "% missing"); c = fromhex(ex, s[k+1], s[k+2]); k += 2; if((c&16rc0) != 2) runtime(ex, URIError, "bad hex number"); o[j] = byte c; } (c, nil, nil) = sys->byte2char(o, 0); if(c < 16r10000){ if(flag && isres(c)){ r += s[start: k+1]; n += k+1-start; } else r[n++] = c; } else if(c > 16r10ffff) runtime(ex, URIError, "bad byte sequence"); else{ r[n++] = ((c-16r10000)&16r3ff)+16rdc00; r[n++] = (((c-16r10000)>>10)&16r3ff)+16rd800; } } } } return r; } cdecodeuri(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val { return strval(decode(ex, toString(ex, biarg(args, 0)), 1)); } cdecodeuric(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val { return strval(decode(ex, toString(ex, biarg(args, 0)), 0)); } cencodeuri(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val { return strval(encode(ex, toString(ex, biarg(args, 0)), 1)); } cencodeuric(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val { return strval(encode(ex, toString(ex, biarg(args, 0)), 0)); }