/*
* BDecoder - Converts an InputStream to BEValues. Copyright (C) 2003 Mark J.
* Wielaard
*
* This file is part of Snark.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.klomp.snark.bencode;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class BEncoder
{
public static byte[] bencode (Object o) throws IllegalArgumentException
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bencode(o, baos);
return baos.toByteArray();
} catch (IOException ioe) {
throw new InternalError(ioe.toString());
}
}
@SuppressWarnings("unchecked")
public static void bencode (Object o, OutputStream out) throws IOException,
IllegalArgumentException
{
if (o instanceof String) {
bencode((String)o, out);
} else if (o instanceof byte[]) {
bencode((byte[])o, out);
} else if (o instanceof Number) {
bencode((Number)o, out);
} else if (o instanceof List) {
bencode((List)o, out);
} else if (o instanceof Map) {
bencode((Map<String, Object>)o, out);
} else {
throw new IllegalArgumentException("Cannot bencode: "
+ o.getClass());
}
}
public static byte[] bencode (String s)
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bencode(s, baos);
return baos.toByteArray();
} catch (IOException ioe) {
throw new InternalError(ioe.toString());
}
}
public static void bencode (String s, OutputStream out) throws IOException
{
byte[] bs = s.getBytes("UTF-8");
bencode(bs, out);
}
public static byte[] bencode (Number n)
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bencode(n, baos);
return baos.toByteArray();
} catch (IOException ioe) {
throw new InternalError(ioe.toString());
}
}
public static void bencode (Number n, OutputStream out) throws IOException
{
out.write('i');
String s = n.toString();
out.write(s.getBytes("UTF-8"));
out.write('e');
}
public static byte[] bencode (List l)
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bencode(l, baos);
return baos.toByteArray();
} catch (IOException ioe) {
throw new InternalError(ioe.toString());
}
}
public static void bencode (List l, OutputStream out) throws IOException
{
out.write('l');
Iterator it = l.iterator();
while (it.hasNext()) {
bencode(it.next(), out);
}
out.write('e');
}
public static byte[] bencode (byte[] bs)
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bencode(bs, baos);
return baos.toByteArray();
} catch (IOException ioe) {
throw new InternalError(ioe.toString());
}
}
public static void bencode (byte[] bs, OutputStream out) throws IOException
{
String l = Integer.toString(bs.length);
out.write(l.getBytes("UTF-8"));
out.write(':');
out.write(bs);
}
public static byte[] bencode (Map<String, Object> m)
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bencode(m, baos);
return baos.toByteArray();
} catch (IOException ioe) {
throw new InternalError(ioe.toString());
}
}
public static void bencode (Map<String, Object> m, OutputStream out)
throws IOException
{
out.write('d');
// Keys must be sorted. XXX - But is this the correct order?
Set<String> s = m.keySet();
List<String> l = new ArrayList<String>(s);
Collections.sort(l);
for (String key : l) {
Object value = m.get(key);
bencode(key, out);
bencode(value, out);
}
out.write('e');
}
}