import ceylon.buffer.charset { ascii, utf8 } Integer fromHex(Integer hex) { if(hex >= '0'.integer && hex <= '9'.integer) { return hex - '0'.integer; } if(hex >= 'A'.integer && hex <= 'F'.integer) { return 10 + hex - 'A'.integer; } if(hex >= 'a'.integer && hex <= 'f'.integer) { return 10 + hex - 'a'.integer; } throw Exception("Invalid hexadecimal number: "+hex.string); } "Decodes a percent-encoded ASCII string." by("Stéphane Épardaud") shared String decodePercentEncoded(String str) { Byte percent = '%'.integer.byte; value array = Array(ascii.encode(str)); variable Integer r = 0; variable Integer w = 0; while(r < array.size) { assert (exists char = array[r]); if(char == percent) { // must read the next two items if (exists first = array[++r]) { if (exists second = array[++r]) { array[w] = (16 * fromHex(first.unsigned) + fromHex(second.unsigned)).byte; } else { throw Exception("Missing second hex number"); } } else { throw Exception("Missing first hex number"); } } else { array[w] = char; } r++; w++; } return utf8.decode(array.take(w)); }