aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/main/java/com/yahoo/searchlib/aggregation/RawData.java
blob: 7c9dd33477baba2c7983df05d1a1dfc6575bcea4 (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
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchlib.aggregation;

import com.yahoo.vespa.objects.Deserializer;
import com.yahoo.vespa.objects.Serializer;

import java.util.Arrays;

/**
 * <p>This class encapsulates a byte array into a cloneable and comparable object. It also implements a sane {@link
 * #hashCode()} and {@link #toString()}.</p>
 *
 * @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen</a>
 */
public class RawData implements Cloneable, Comparable<RawData> {

    private byte[] data;

    /**
     * <p>Constructs an empty data object.</p>
     */
    public RawData() {
        data = new byte[0];
    }

    /**
     * <p>Constructs a raw data object that holds the given byte array.</p>
     *
     * @param data The rank to set.
     */
    public RawData(byte[] data) {
        setData(data);
    }

    /**
     * <p>Serializes the content of this data into the given byte buffer.</p>
     *
     * @param buf The buffer to serialize to.
     */
    public void serialize(Serializer buf) {
        buf.putInt(null, data.length);
        buf.put(null, data);
    }

    /**
     * <p>Deserializes the content for this data from the given byte buffer.</p>
     *
     * @param buf The buffer to deserialize from.
     */
    public void deserialize(Deserializer buf) {
        int len = buf.getInt(null);
        data = buf.getBytes(null, len);
    }

    /**
     * <p>Returns the byte array that constitutes this data.</p>
     *
     * @return The byte array.
     */
    public byte[] getData() {
        return data;
    }

    /**
     * <p>Sets the byte array that constitutes this data. This does <b>not</b> copy the given array, it simply assigns
     * it to this.</p>
     *
     * @param data The data to set.
     * @return This, to allow chaining.
     */
    public RawData setData(byte[] data) {
        if (data == null) {
            throw new IllegalArgumentException("Data can not be null.");
        }
        this.data = data;
        return this;
    }

    @Override
    public int compareTo(RawData rhs) {
        return compare(data, rhs.data);
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof RawData)) {
            return false;
        }
        RawData rhs = (RawData)obj;
        if (!Arrays.equals(data, rhs.data)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(data);
    }

    @Override
    public String toString() {
        return "RawData(data = " + Arrays.toString(data) + ")";
    }

    @Override
    public Object clone() {
        return new RawData(Arrays.copyOf(data, data.length));
    }

    /**
     * <p>Implements comparison of two byte arrays.</p>
     *
     * @param lhs The left-hand-side of the comparison.
     * @param rhs The right-hand-side of the comparison.
     * @return The result of comparing the two byte arrays.
     */
    public static int compare(byte[] lhs, byte[] rhs) {
        int cmp = 0;
        for (int i = 0, len = Math.min(lhs.length, rhs.length); (i < len) && (cmp == 0); i++) {
            int a = lhs[i] & 0xFF;
            int b = rhs[i] & 0xFF;
            cmp = a - b;
        }
        if (cmp == 0) {
            cmp = lhs.length - rhs.length;
        }
        return cmp;
    }
}