Advertisement
Guest User

Java bencode - BDecoder.java

a guest
Apr 11th, 2010
829
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.61 KB | None | 0 0
  1. package bencode;
  2.  
  3. import java.io.InputStream;
  4. import java.io.IOException;
  5. import java.nio.charset.Charset;
  6. import java.util.List;
  7. import java.util.ArrayList;
  8. import java.util.Map;
  9. import java.util.HashMap;
  10.  
  11. public class BDecoder {
  12.  
  13.     private InputStream in;
  14.     private Charset charset;
  15.  
  16.     public BDecoder(InputStream in) {
  17.         this(in, Charset.forName("UTF-8"));
  18.     }
  19.  
  20.     public BDecoder(InputStream in, Charset charset) {
  21.         this.in = in;
  22.         this.charset = charset;
  23.     }
  24.  
  25.     public Object decode() throws IOException, BencodeFormatException {
  26.        
  27.         int indicator;
  28.         int strLen;
  29.  
  30.         while ((indicator = in.read()) != -1) {
  31.             if (indicator == 'i') {
  32.                 return readNumber();
  33.             } else if (Character.isDigit(indicator)) {
  34.                 strLen = readStringLength((char) indicator);
  35.                 return readString(strLen);
  36.             } else if (indicator == 'l') {
  37.                 return readList();
  38.             } else if (indicator == 'd') {
  39.                 return readMap();
  40.             } else if (indicator == 'e') {
  41.                 return null;
  42.             } else {
  43.                 throw new BencodeFormatException(
  44.                         "Incorrect indicator character: " + (char) indicator);
  45.             }
  46.         }
  47.  
  48.         return null;
  49.  
  50.     }
  51.  
  52.     public Map decodeMap() throws IOException, BencodeFormatException {
  53.  
  54.         int indicator = in.read();
  55.  
  56.         if (indicator == 'd') {
  57.             return readMap();
  58.         } else if (indicator == -1) {
  59.             throw new BencodeFormatException("Unexpected end of stream.");
  60.         } else {
  61.             throw new BencodeFormatException("Incorrect indicator character: "
  62.                     + (char) indicator);
  63.         }
  64.  
  65.     }
  66.  
  67.     private String readString(int len) throws IOException {
  68.  
  69.         byte[] result = new byte[len];
  70.         int read = 0;
  71.         int num = 0;
  72.  
  73.         while (read < len) {
  74.             num = in.read(result, read, len - read);
  75.             read += num;
  76.         }
  77.  
  78.         return new String(result, charset);
  79.  
  80.     }
  81.  
  82.     private int readStringLength(char startChar)
  83.             throws IOException, BencodeFormatException {
  84.  
  85.         StringBuilder lenStr = new StringBuilder(64);
  86.         int c;
  87.  
  88.         lenStr.append(startChar);
  89.  
  90.         while (true) {
  91.             c = in.read();
  92.             if (Character.isDigit(c)) {
  93.                 lenStr.append((char) c);
  94.             } else if (c == ':') {
  95.                 break;
  96.             } else if (c == -1) {
  97.                 throw new BencodeFormatException("Unexpected end of stream.");
  98.             } else {
  99.                 throw new BencodeFormatException("Character ('" + (char) c
  100.                         + "') not allowed in integer declaration.");
  101.             }
  102.         }
  103.        
  104.         return Integer.parseInt(lenStr.toString());
  105.  
  106.     }
  107.  
  108.     private Long readNumber() throws IOException, BencodeFormatException {
  109.  
  110.         StringBuilder numStr = new StringBuilder(64);
  111.         int c = in.read();
  112.  
  113.         if (Character.isDigit(c) || c == '-') {
  114.             numStr.append((char) c);
  115.         } else {
  116.             throw new BencodeFormatException(
  117.                     "Integer must begin with digit or '-' character.");
  118.         }
  119.  
  120.         while (true) {
  121.             c = in.read();
  122.             if (Character.isDigit(c)) {
  123.                 numStr.append((char) c);
  124.             } else if (c == 'e') {
  125.                 break;
  126.             } else if (c == -1) {
  127.                 throw new BencodeFormatException("Unexpected end of stream.");
  128.             } else {
  129.                 throw new BencodeFormatException("Character ('" + (char) c
  130.                         + "') not allowed in integer declaration.");
  131.             }
  132.         }
  133.  
  134.         return new Long(numStr.toString());
  135.  
  136.     }
  137.  
  138.     private List readList() throws IOException, BencodeFormatException {
  139.  
  140.         List list = new ArrayList();
  141.         Object o;
  142.  
  143.         while ((o = decode()) != null) {
  144.             list.add(o);
  145.         }
  146.  
  147.         return list;
  148.  
  149.     }
  150.  
  151.     private Map readMap() throws IOException, BencodeFormatException {
  152.  
  153.         Map map = new HashMap<String, Object>();
  154.         Object key;
  155.         Object value;
  156.  
  157.         while ((key =  decode()) != null) {
  158.             value = decode();
  159.             if (value == null) {
  160.                 throw new BencodeFormatException(
  161.                         "Bad dictionary format: value for key \"" + key
  162.                         + "\" not found.");
  163.             }
  164.             map.put(key, value);
  165.         }
  166.  
  167.         return map;
  168.  
  169.     }
  170.  
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement