aboutsummaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/reader/ParamReader.java
blob: 5232326aae7c0cf1244cb502a94b0e92fe9bfe26 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package cz.crcs.ectester.reader;

import cz.crcs.ectester.applet.EC_Consts;

import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;

/**
 * @author Jan Jancar johny@neuromancer.sk
 */
public class ParamReader {
    private static final Pattern hex = Pattern.compile("[a-fA-F\\d]+");

    /**
     * Flattens params read from String[] data into a byte[] with their lengths prepended as short entries.
     * @param params (EC_Consts.PARAMETER_* | ...)
     * @param data data read by readString, readFile, readResource
     * @return byte[] with params flattened
     */
    public static byte[] flatten(short params, String[] data) {
        if (!validate(data)) {
            return null;
        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        short paramMask = EC_Consts.PARAMETER_FP;
        int i = 0;
        while (paramMask <= EC_Consts.PARAMETER_S) {
            short masked = (short) (params & paramMask);
            if (masked != 0) {
                byte[] param = parse(data[i]);
                if (masked == EC_Consts.PARAMETER_F2M && data.length == 9) {
                    //read and pad and append e_2, e_3
                    param = Util.concatenate(param, parse(data[i + 1]), parse(data[i + 2]));
                    i += 2;
                    if (param.length != 6)
                        return null;
                }
                if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) {
                    //read another param (the y coord) and put into X962 format.
                    byte[] y = parse(data[i + 1]);
                    param = Util.concatenate(new byte[]{4}, param, y);
                    i++;
                }
                if (param.length == 0)
                    return null;

                //write length
                byte[] length = new byte[2];
                Util.setShort(length, 0, (short) param.length);
                out.write(length, 0, 2);
                //write data
                out.write(param, 0, param.length);
                i++;
            }
            paramMask = (short) (paramMask << 1);
        }

        return (out.size() == 0) ? null : out.toByteArray();
    }

    /**
     * Reads hex params from a CSV String data.
     * @param data String containing CSV data(hex)
     * @return String array containing the CSV entries
     */
    public static String[] readString(String data) {
        return read(new ByteArrayInputStream(data.getBytes()));
    }

    /**
     * Reads hex params from a CSV Resource (inside jar).
     * @param resourcePath path to the resourse
     * @return String array containing the CSV entries
     */
    public static String[] readResource(String resourcePath) {
        return read(ParamReader.class.getResourceAsStream(resourcePath));
    }

    /**
     * Reads hex params from a CSV file.
     * @param filePath path to the file
     * @return String array containing the CSV entries
     * @throws FileNotFoundException if the file cannot be opened
     */
    public static String[] readFile(String filePath) throws FileNotFoundException {
        return read(new FileInputStream(filePath));
    }

    private static String[] read(InputStream in) {
        Scanner s = new Scanner(in);

        s.useDelimiter(",|;");
        List<String> data = new LinkedList<String>();
        while (s.hasNext()) {
            String field = s.next();
            data.add(field.replaceAll("\\s+", ""));
        }
        return data.toArray(new String[data.size()]);
    }

    private static boolean validate(String[] data) {
        if (data == null || data.length == 0) {
            return false;
        }
        for (String param : data) {
            if (!hex.matcher(param).matches()) {
                return false;
            }
        }
        return true;
    }

    private static byte[] parse(String hex) {
        byte[] data = Util.hexToBytes(hex);
        if (data == null)
            return new byte[0];
        if (data.length < 2)
            return pad(data);
        return data;
    }

    private static byte[] pad(byte[] data) {
        if (data.length == 1) {
            return new byte[]{(byte) 0, data[0]};
        } else if (data.length == 0 || data.length > 2) {
            return data;
        }
        return null;
    }
}