OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Blame | Last modification | View Log | RSS feed

/*
 * 
 */

/*
 * Created on Jul 7, 2005
 */
package com.zimbra.common.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author dkarp
 */
public class BEncoding {

    public static final class BEncodingException extends Exception {
        BEncodingException(String msg)   { super(msg); }
        BEncodingException(Exception e)  { super(e); }
    }

    public static String encode(Map object) {
        return encode(new StringBuffer(), object).toString();
    }
    public static String encode(List object) {
        return encode(new StringBuffer(), object).toString();
    }

    public static Object decode(String data) throws BEncodingException {
        if (data == null)
            return null;
        try {
            Offset offset = new Offset();
            Object result = decode(data.toCharArray(), offset);
            if (offset.offset != data.length())
                throw new BEncodingException("extra characters at end of encoded string");
            return result;
        } catch (BEncodingException e) {
            throw e;
        } catch (Exception e) {
            throw new BEncodingException(e);
        }
    }


    private static StringBuffer encode(StringBuffer sb, Object object) {
        if (object instanceof Map) {
            SortedMap tree = (object instanceof SortedMap ? (SortedMap) object : new TreeMap((Map) object));
            sb.append('d');
            if (!tree.isEmpty())
                for (Iterator it = tree.entrySet().iterator(); it.hasNext(); ) {
                    Map.Entry entry = (Map.Entry) it.next();
                    if (entry.getKey() != null && entry.getValue() != null) {
                        encode(sb, entry.getKey().toString());
                        encode(sb, entry.getValue());
                    }
                }
            sb.append('e');
        } else if (object instanceof List) {
            Object value;
            sb.append('l');
            for (Iterator it = ((List) object).iterator(); it.hasNext(); )
                if ((value = it.next()) != null)
                    encode(sb, value);
            sb.append('e');
        } else if (object instanceof Long || object instanceof Integer || object instanceof Short || object instanceof Byte) {
            sb.append('i').append(object).append('e');
        } else if (object != null) {
            String value = object.toString();
            sb.append(value.length()).append(':').append(value);
        }
        return sb;
    }

    private static final class Offset {
        int offset;
    }

    private static Object decode(char[] buffer, Offset offset) throws BEncodingException {
        Object key, value;
        char c = buffer[offset.offset++];
        switch (c) {
            case 'd':
                Map map = new HashMap();
                while ((key = decode(buffer, offset)) != null) {
                    if ((value = decode(buffer, offset)) == null)
                        throw new BEncodingException("missing dictionary value for key " + key.toString());
                    map.put(key.toString(), value);
                }
                return map;

            case 'l':
                List list = new ArrayList();
                while ((key = decode(buffer, offset)) != null)
                    list.add(key);
                return list;

            case 'e':
                return null;

            case 'i':
                return new Long(readLong(buffer, offset, 'e'));

            default:
                offset.offset--;
                long length = readLong(buffer, offset, ':');
                int start = offset.offset;
                offset.offset += length;
                return new String(buffer, start, (int) length);
        }
    }

    private static long readLong(char[] buffer, Offset offset, char terminator) {
        int start = offset.offset;
        while (buffer[offset.offset++] != terminator) ;
        return Long.parseLong(new String(buffer, start, offset.offset - start - 1));
    }

    public static void main(String[] args) throws BEncodingException {
        List list = new ArrayList();
        list.add(new Integer(654));
        list.add("hwhergk");
        list.add(new StringBuffer("74x"));
        Map map = new HashMap();
        map.put("testing", new Long(5));
        map.put("foo2", "bar");
        map.put("herp", list);
        map.put("Foo", new Float(6.7));
        map.put("yy", new TreeMap());
        String encoded = encode(map);
        System.out.println(encoded);
        System.out.println(decode(encoded));
    }
}