Package co.nstant.in.cbor.encoder

Source Code of co.nstant.in.cbor.encoder.MapEncoder

package co.nstant.in.cbor.encoder;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Comparator;
import java.util.TreeMap;

import co.nstant.in.cbor.CborEncoder;
import co.nstant.in.cbor.CborException;
import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.MajorType;
import co.nstant.in.cbor.model.Map;
import co.nstant.in.cbor.model.SimpleValue;

public class MapEncoder extends AbstractEncoder<Map> {

    public MapEncoder(CborEncoder encoder, OutputStream outputStream) {
        super(encoder, outputStream);
    }

    @Override
    public void encode(Map map) throws CborException {
        Collection<DataItem> keys = map.getKeys();
        if (map.isChunked()) {
            encodeTypeChunked(MajorType.MAP);
        } else {
            encodeTypeAndLength(MajorType.MAP, keys.size());
        }

        if (keys.isEmpty()) {
            return;
        }

        if (map.isChunked()) {
            for (DataItem key : keys) {
                encoder.encode(key);
                encoder.encode(map.get(key));
            }
            encoder.encode(SimpleValue.BREAK);
            return;
        }

        /**
         * The keys in every map must be sorted lowest value to highest. Sorting
         * is performed on the bytes of the representation of the key data items
         * without paying attention to the 3/5 bit splitting for major types.
         * (Note that this rule allows maps that have keys of different types,
         * even though that is probably a bad practice that could lead to errors
         * in some canonicalization implementations.) The sorting rules are:
         *
         * If two keys have different lengths, the shorter one sorts earlier;
         *
         * If two keys have the same length, the one with the lower value in
         * (byte-wise) lexical order sorts earlier.
         */

        TreeMap<byte[], byte[]> sortedMap = new TreeMap<>(
                        new Comparator<byte[]>() {

                            @Override
                            public int compare(byte[] o1, byte[] o2) {
                                if (o1.length < o2.length) {
                                    return -1;
                                }
                                if (o1.length > o2.length) {
                                    return 1;
                                }
                                for (int i = 0; i < o1.length; i++) {
                                    if (o1[i] < o2[i]) {
                                        return -1;
                                    }
                                    if (o1[i] > o2[i]) {
                                        return 1;
                                    }
                                }
                                return 0;
                            }

                        });
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        CborEncoder e = new CborEncoder(byteArrayOutputStream);
        for (DataItem key : keys) {
            // Key
            e.encode(key);
            byte[] keyBytes = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.reset();
            // Value
            e.encode(map.get(key));
            byte[] valueBytes = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.reset();
            sortedMap.put(keyBytes, valueBytes);
        }
        for (java.util.Map.Entry<byte[], byte[]> entry : sortedMap.entrySet()) {
            write(entry.getKey());
            write(entry.getValue());
        }
    }

}
TOP

Related Classes of co.nstant.in.cbor.encoder.MapEncoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.