All Downloads are FREE. Search and download functionalities are using the official Maven repository.

herddb.utils.RawString Maven / Gradle / Ivy

The newest version!
/*
 Licensed to Diennea S.r.l. under one
 or more contributor license agreements. See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership. Diennea S.r.l. licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.

 */

package herddb.utils;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.netty.util.Recycler;
import java.nio.charset.StandardCharsets;

/**
 * A container for strings. Data is decoded to a real java.lang.String only if
 * needed
 *
 * @author enrico.olivelli
 */
@SuppressFBWarnings(value = {"EI_EXPOSE_REP"})
public class RawString implements Comparable {

    private final Recycler.Handle handle;

    @SuppressFBWarnings(value = "EI_EXPOSE_REP2")
    private byte[] data;
    private int offset;
    private int length;
    private String string;
    private int hashcode;

    public static final RawString EMPTY = newUnpooledRawString(new byte[0], 0, 0);

    private static final Recycler RECYCLER = new Recycler() {
        @Override
        protected RawString newObject(Recycler.Handle handle) {
            return new RawString(handle);
        }
    };

    public RawString(Recycler.Handle handle) {
        this.handle = handle;
    }

    public static RawString newPooledRawString(byte[] data, int offset, int length, String string) {
        RawString res = RECYCLER.get();
        res.data = data;
        res.offset = offset;
        res.length = length;
        res.string = string;
        res.hashcode = -1;
        return res;
    }

    public static RawString newPooledRawString(byte[] data, int offset, int length) {
        RawString res = RECYCLER.get();
        res.data = data;
        res.offset = offset;
        res.length = length;
        res.string = null;
        res.hashcode = -1;
        return res;
    }

    public static RawString newUnpooledRawString(byte[] data, int offset, int length) {
        RawString res = new RawString(null);
        res.data = data;
        res.offset = offset;
        res.length = length;
        res.string = null;
        res.hashcode = -1;
        return res;
    }

    public static RawString newUnpooledRawString(byte[] data, int offset, int length, String string) {
        RawString res = new RawString(null);
        res.data = data;
        res.offset = offset;
        res.length = length;
        res.string = string;
        res.hashcode = -1;
        return res;
    }

    public static RawString of(String string) {
        if (string.isEmpty()) {
            return EMPTY;
        }
        byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
        return newUnpooledRawString(bytes, 0, bytes.length, string);
    }

    public void recycle() {
        if (handle != null) {
            this.data = null;
            this.string = null;
            handle.recycle(this);
        }
    }

    @Override
    public int hashCode() {
        if (hashcode == -1) {
            this.hashcode = CompareBytesUtils.hashCode(data, offset, length);
        }
        return hashcode;
    }

    @SuppressFBWarnings(value = "EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS")
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (obj instanceof RawString) {
            final RawString other = (RawString) obj;
            return (this.hashCode() == other.hashCode())
                    && CompareBytesUtils.arraysEquals(this.data, offset, offset + length,
                    other.data, other.offset, other.length + other.offset);
        }
        if (obj instanceof Boolean) {
            boolean b = (Boolean) obj;
            return b ? CompareBytesUtils.arraysEquals(this.data, offset, length + offset,
                    TRUE, 0, 4)
                    : CompareBytesUtils.arraysEquals(this.data, offset, length + offset,
                    FALSE, 0, 5);
        }
        String otherString = obj.toString();
        byte[] other_data = otherString
                .getBytes(StandardCharsets.UTF_8);
        return CompareBytesUtils.arraysEquals(this.data, offset, this.length + offset,
                other_data, 0, other_data.length);
    }

    private static final byte[] TRUE = "true".getBytes(StandardCharsets.UTF_8);
    private static final byte[] FALSE = "false".getBytes(StandardCharsets.UTF_8);

    @Override
    public String toString() {
        String _string = string;
        if (_string != null) {
            return _string;
        }
        return string = new String(data, offset, length, StandardCharsets.UTF_8);
    }

    @Override
    public int compareTo(RawString o) {
        return compareRaw(this.data, this.offset, this.length,
                o.data, o.offset, o.length);
    }

    public int compareToString(String o) {
        return compareRaw(this.data, this.offset, this.length, o);
    }

    public static int compareRaw(byte[] left, int offset, int leftlen, byte[] right, int offsetright, int lenright) {
        return CompareBytesUtils
                .compare(left, offset, leftlen + offset,
                        right, offsetright, lenright + offsetright);
    }

    public static int compareRaw(byte[] left, int offset, int leftlen, RawString other) {
        return CompareBytesUtils
                .compare(left, offset, leftlen + offset,
                        other.data, other.offset, other.length);
    }

    public static int compareRaw(byte[] left, int offset, int leftlen, String other) {
        byte[] right = other.getBytes(StandardCharsets.UTF_8);
        return CompareBytesUtils
                .compare(left, offset, leftlen + offset,
                        right, 0, right.length);
    }

    public byte[] getData() {
        return data;
    }

    public int getOffset() {
        return offset;
    }

    public int getLength() {
        return length;
    }

    public byte[] toByteArray() {
        if (offset == 0 && length == data.length) {
            // no copy
            return data;
        }
        byte[] copy = new byte[length];
        System.arraycopy(data, offset, copy, 0, length);
        return copy;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy