RFC 3986 Percent Encoding


See RFC 3986 2.1 Percent Encoding.

너무나도 간단하지만 아직 이름도 못들어 본 개발자(犬足者)들이 많은 것 같아서 몇 줄 적어본다.

Encoding

for a given octet,
if one of [ ALPHA / DIGIT / "-" / "." / "_" / "~" ]
    do not encode
else
    encode as [ "%" HEXDIG HEXDIG ]

Decoding

No comments!

Case Sensitivity?

For consistency, URI producers and normalizers should use uppercase hexadecimal digits for all percent-encodings.

Java

// '0' to '9' and 'A' to 'F'
static final int[] H = new int[] {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};


static final Map<Integer, Integer> I;

static {
    final Map<Integer, Integer> m = new HashMap<Integer, Integer>();
    for (int i = 0; i < H.length; i++) {
        m.put(H[i], i);
    }
    I = Collections.<Integer, Integer>unmodifiableMap(m);
}


static void encode(final InputStream decoded, final OutputStream encoded)
    throws IOException {

    for (int b = -1; (b = decoded.read()) != -1; ) {
        if ((b >= 0x30 && b <= 0x39)                               // '0' - '9'
            || (b >= 0x41 && b <= 0x5A)                            // 'A' - 'Z'
            || (b >= 0x61 && b <= 0x7A)                            // 'a' - 'z'
            || b == 0x2D || b == 0x5F || b == 0x2E || b == 0x7E) { // '-' '_' '.' '~'
            encoded.write(b);
        } else {
            encoded.write(0x25); // '%'
            encoded.write(H[(b >> 4)]);
            encoded.write(H[(b & 0x0F)]);
        }
    }
}


static void decode(final InputStream encoded, final OutputStream decoded)
    throws IOException {

    int h;
    int l;
    for (int b = -1; (b = encoded.read()) != -1; ) {
        if ((b >= 0x30 && b <= 0x39)                               // '0' - '9'
            || (b >= 0x41 && b <= 0x5A)                            // 'A' - 'Z'
            || (b >= 0x61 && b <= 0x7A)                            // 'a' - 'z'
            || b == 0x2D || b == 0x5F || b == 0x2E || b == 0x7E) { // '-' '_' '.' '~'
            decoded.write(b);
        } else {
            if (b != 0x25) throw new IOException("expected '%'");
            if ((h= encoded.read()) == -1) throw new EOFException("eof");
            if (!I.containsKey(h))  throw new IOException("illegal HEXDIG");
            if ((l= encoded.read()) == -1) throw new EOFException("eof");
            if (!I.containsKey(l))  throw new IOException("illegal HEXDIG");
            decoded.write((I.get(h) << 4) | I.get(l));
        }
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s