001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.activemq.util;
019
020import java.util.Arrays;
021
022public class ByteSequence {
023
024    public byte[] data;
025    public int offset;
026    public int length;
027
028    public ByteSequence() {
029    }
030
031    public ByteSequence(byte data[]) {
032        this.data = data;
033        this.offset = 0;
034        this.length = data.length;
035    }
036
037    public ByteSequence(byte data[], int offset, int length) {
038        this.data = data;
039        this.offset = offset;
040        this.length = length;
041    }
042
043    public byte[] getData() {
044        return data;
045    }
046
047    public int getLength() {
048        return length;
049    }
050
051    public int getOffset() {
052        return offset;
053    }
054
055    public int remaining() { return length - offset; }
056
057    public void setData(byte[] data) {
058        this.data = data;
059    }
060
061    public void setLength(int length) {
062        this.length = length;
063    }
064
065    public void setOffset(int offset) {
066        this.offset = offset;
067    }
068
069    public void compact() {
070        if (length != data.length) {
071            byte t[] = new byte[length];
072            System.arraycopy(data, offset, t, 0, length);
073            data = t;
074            offset = 0;
075        }
076    }
077
078    public void reset() {
079        length = remaining();
080        if (length > 0) {
081            System.arraycopy(data, offset, data, 0, length);
082        } else {
083            length = 0;
084        }
085        offset = 0;
086    }
087
088    public int indexOf(ByteSequence needle, int pos) {
089        int max = length - needle.length - offset;
090        for (int i = pos; i < max; i++) {
091            if (matches(needle, i)) {
092                return i;
093            }
094        }
095        return -1;
096    }
097
098    private boolean matches(ByteSequence needle, int pos) {
099        for (int i = 0; i < needle.length; i++) {
100            if( data[offset + pos+ i] != needle.data[needle.offset + i] ) {
101                return false;
102            }
103        }
104        return true;
105    }
106
107    private byte getByte(int i) {
108        return data[offset+i];
109    }
110
111    final public int indexOf(byte value, int pos) {
112        for (int i = pos; i < length; i++) {
113            if (data[offset + i] == value) {
114                return i;
115            }
116        }
117        return -1;
118    }
119
120    public boolean startsWith(final byte[] bytes) {
121        if (length - offset < bytes.length) {
122            return false;
123        }
124        for (int i = 0; i<bytes.length; i++) {
125            if (data[offset+i] != bytes[i]) {
126                return false;
127            }
128        }
129        return true;
130    }
131
132    /**
133     * Makes a deep copy of the data into a new byte array
134     * starting at the offset.
135     *
136     * @return
137     */
138    public byte[] toArray() {
139        return Arrays.copyOfRange(getData(), getOffset(), getLength());
140    }
141}