| 1 | // Copyright (c) 2006 Dustin Sallings <dustin@spy.net> |
| 2 | |
| 3 | package net.spy.memcached.transcoders; |
| 4 | |
| 5 | /** |
| 6 | * Utility class for transcoding Java types. |
| 7 | */ |
| 8 | public final class TranscoderUtils { |
| 9 | |
| 10 | private final boolean packZeros; |
| 11 | |
| 12 | /** |
| 13 | * Get an instance of TranscoderUtils. |
| 14 | * |
| 15 | * @param pack if true, remove all zero bytes from the MSB of the packed num |
| 16 | */ |
| 17 | public TranscoderUtils(boolean pack) { |
| 18 | super(); |
| 19 | packZeros=pack; |
| 20 | } |
| 21 | |
| 22 | public byte[] encodeNum(long l, int maxBytes) { |
| 23 | byte[] rv=new byte[maxBytes]; |
| 24 | for(int i=0; i<rv.length; i++) { |
| 25 | int pos=rv.length-i-1; |
| 26 | rv[pos]=(byte) ((l >> (8 * i)) & 0xff); |
| 27 | } |
| 28 | if(packZeros) { |
| 29 | int firstNon0=0; |
| 30 | for(;firstNon0<rv.length && rv[firstNon0]==0; firstNon0++) { |
| 31 | // Just looking for what we can reduce |
| 32 | } |
| 33 | if(firstNon0 > 0) { |
| 34 | byte[] tmp=new byte[rv.length - firstNon0]; |
| 35 | System.arraycopy(rv, firstNon0, tmp, 0, rv.length-firstNon0); |
| 36 | rv=tmp; |
| 37 | } |
| 38 | } |
| 39 | return rv; |
| 40 | } |
| 41 | |
| 42 | public byte[] encodeLong(long l) { |
| 43 | return encodeNum(l, 8); |
| 44 | } |
| 45 | |
| 46 | public long decodeLong(byte[] b) { |
| 47 | long rv=0; |
| 48 | for(byte i : b) { |
| 49 | rv = (rv << 8) | (i<0?256+i:i); |
| 50 | } |
| 51 | return rv; |
| 52 | } |
| 53 | |
| 54 | public byte[] encodeInt(int in) { |
| 55 | return encodeNum(in, 4); |
| 56 | } |
| 57 | |
| 58 | public int decodeInt(byte[] in) { |
| 59 | assert in.length <= 4 |
| 60 | : "Too long to be an int (" + in.length + ") bytes"; |
| 61 | return (int)decodeLong(in); |
| 62 | } |
| 63 | |
| 64 | public byte[] encodeByte(byte in) { |
| 65 | return new byte[]{in}; |
| 66 | } |
| 67 | |
| 68 | public byte decodeByte(byte[] in) { |
| 69 | assert in.length <= 1 : "Too long for a byte"; |
| 70 | byte rv=0; |
| 71 | if(in.length == 1) { |
| 72 | rv=in[0]; |
| 73 | } |
| 74 | return rv; |
| 75 | } |
| 76 | |
| 77 | public byte[] encodeBoolean(boolean b) { |
| 78 | byte[] rv=new byte[1]; |
| 79 | rv[0]=(byte)(b?'1':'0'); |
| 80 | return rv; |
| 81 | } |
| 82 | |
| 83 | public boolean decodeBoolean(byte[] in) { |
| 84 | assert in.length == 1 : "Wrong length for a boolean"; |
| 85 | return in[0] == '1'; |
| 86 | } |
| 87 | |
| 88 | } |