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

org.apache.qpid.framing.EncodingUtils Maven / Gradle / Ivy

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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 org.apache.qpid.framing;

import java.nio.charset.StandardCharsets;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.bytebuffer.QpidByteBuffer;

public class EncodingUtils
{
    private static final Logger _logger = LoggerFactory.getLogger(EncodingUtils.class);

    private EncodingUtils()
    {
    }

    public static int encodedShortStringLength(String s)
    {
        if (s == null)
        {
            return 1;
        }
        else
        {
            int size =  1 + getUTF8Length(s);
            if(size > 256)
            {
                throw new IllegalArgumentException("String '"+s+"' is too long - over 255 octets to encode");
            }
            return (short) size;
        }
    }

    public static int encodedShortStringLength(long l)
    {
        if (l == 0)
        {
            return 2;
        }
        else if(l>=1000000000000L && l<10000000000000L)
        {
            // this covers the common case of timestamps between Sep 2010 and Nov 2286
            return 14;
        }
        else
        {
            return Long.toString(l).length()+1;
        }
    }

    public static int encodedShortStringLength(AMQShortString s)
    {
        if (s == null)
        {
            return 1;
        }
        else
        {
            return (1 + s.length());
        }
    }

    public static int encodedLongStringLength(String s)
    {
        if (s == null)
        {
            return 4;
        }
        else
        {
            return 4 + getUTF8Length(s);
        }
    }

    public static int encodedLongstrLength(byte[] bytes)
    {
        if (bytes == null)
        {
            return 4;
        }
        else
        {
            return 4 + bytes.length;
        }
    }

    public static int encodedFieldTableLength(FieldTable table)
    {
        if (table == null)
        {
            // length is encoded as 4 octets
            return 4;
        }
        else
        {
            // length of the table plus 4 octets for the length
            return (int) table.getEncodedSize() + 4;
        }
    }

    public static void writeLongAsShortString(QpidByteBuffer buffer, long l)
    {
        String s = Long.toString(l);
        byte[] encodedString = new byte[1+s.length()];
        char[] cha = s.toCharArray();
        encodedString[0] = (byte) s.length();
        for (int i = 0; i < cha.length; i++)
        {
            encodedString[i+1] = (byte) cha[i];
        }
        buffer.put(encodedString);

    }


    public static void writeShortStringBytes(QpidByteBuffer buffer, AMQShortString s)
    {
        if (s != null)
        {
            s.writeToBuffer(buffer);
        }
        else
        {
            // really writing out unsigned byte
            buffer.put((byte) 0);
        }
    }

    public static void writeLongStringBytes(QpidByteBuffer buffer, String s)
    {
        if (s != null)
        {
            int len = getUTF8Length(s);
            buffer.putUnsignedInt((long) len);
            buffer.put(asUTF8Bytes(s));

        }
        else
        {
            buffer.putUnsignedInt((long) 0);
        }
    }

    public static int unsignedIntegerLength()
    {
        return 4;
    }

    public static void writeFieldTableBytes(QpidByteBuffer buffer, FieldTable table)
    {
        if (table != null)
        {
            table.writeToBuffer(buffer);
        }
        else
        {
            buffer.putUnsignedInt((long) 0);
        }
    }

    public static void writeLongstr(QpidByteBuffer buffer, byte[] data)
    {
        if (data != null)
        {
            buffer.putUnsignedInt((long) data.length);
            buffer.put(data);
        }
        else
        {
            buffer.putUnsignedInt((long) 0);
        }
    }

    public static FieldTable readFieldTable(QpidByteBuffer input) throws AMQFrameDecodingException
    {
        long length = input.getUnsignedInt();
        if (length == 0)
        {
            return null;
        }
        else
        {
            return new FieldTable(input, (int) length);
        }
    }


    public static String readLongString(QpidByteBuffer buffer)
    {
        long length = ((long)(buffer.getInt())) & 0xFFFFFFFFL;
        if (length == 0)
        {
            return "";
        }
        else
        {
            byte[] stringBytes = new byte[(int) length];
            buffer.get(stringBytes, 0, (int) length);

            return new String(stringBytes, StandardCharsets.UTF_8);
        }
    }

    public static byte[] readLongstr(QpidByteBuffer buffer)
    {
        long length = ((long)(buffer.getInt())) & 0xFFFFFFFFL;
        if (length == 0)
        {
            return null;
        }
        else
        {
            byte[] result = new byte[(int) length];
            buffer.get(result);

            return result;
        }
    }

    // **** new methods

    // AMQP_BOOLEAN_PROPERTY_PREFIX

    public static void writeBoolean(QpidByteBuffer buffer, boolean aBoolean)
    {
        buffer.put(aBoolean ? (byte)1 : (byte)0);
    }

    public static int encodedBooleanLength()
    {
        return 1;
    }

    public static int encodedByteLength()
    {
        return 1;
    }

    public static int encodedShortLength()
    {
        return 2;
    }

    public static int encodedIntegerLength()
    {
        return 4;
    }

    public static int encodedLongLength()
    {
        return 8;
    }

    public static int encodedFloatLength()
    {
        return 4;
    }

    public static int encodedDoubleLength()
    {
        return 8;
    }

    public static byte[] readBytes(QpidByteBuffer buffer)
    {
        long length = buffer.getUnsignedInt();
        if (length == 0)
        {
            return null;
        }
        else
        {
            byte[] dataBytes = new byte[(int)length];
            buffer.get(dataBytes);

            return dataBytes;
        }
    }

    public static void writeBytes(QpidByteBuffer buffer, byte[] data)
    {
        if (data != null)
        {
            // TODO: check length fits in an unsigned byte
            buffer.putUnsignedInt((long)data.length);
            buffer.put(data);
        }
        else
        {
            buffer.putUnsignedInt(0L);
        }
    }

    // CHAR_PROPERTY
    public static int encodedCharLength()
    {
        return encodedByteLength();
    }

    public static long readLongAsShortString(QpidByteBuffer buffer)
    {
        short length = buffer.getUnsignedByte();
        short pos = 0;
        if (length == 0)
        {
            return 0L;
        }

        byte digit = buffer.get();
        boolean isNegative;
        long result = 0;
        if (digit == (byte) '-')
        {
            isNegative = true;
            pos++;
            digit = buffer.get();
        }
        else
        {
            isNegative = false;
        }

        result = digit - (byte) '0';
        pos++;

        while (pos < length)
        {
            pos++;
            digit = buffer.get();
            result = (result << 3) + (result << 1);
            result += digit - (byte) '0';
        }

        return isNegative ? -result : result;
    }

    public static byte[] asUTF8Bytes(CharSequence string)
    {
        byte[] bytes = new byte[getUTF8Length(string)];
        int j = 0;
        if(string != null)
        {
            final int length = string.length();
            int c;

            for (int i = 0; i < length; i++)
            {
                c = string.charAt(i);
                if ((c & 0xFF80) == 0)          /* U+0000..U+007F */
                {
                    bytes[j++] = (byte) c;
                }
                else if ((c & 0xF800) == 0)     /* U+0080..U+07FF */
                {
                    bytes[j++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
                    bytes[j++] = (byte) (0x80 | (c & 0x3F));
                }
                else if ((c & 0xD800) != 0xD800 || (c > 0xDBFF))     /* U+0800..U+FFFF - excluding surrogate pairs */
                {
                    bytes[j++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
                    bytes[j++] = (byte) (0x80 | ((c >> 6) & 0x3F));
                    bytes[j++] = (byte) (0x80 | (c & 0x3F));
                }
                else
                {
                    int low;

                    if ((++i == length) || ((low = string.charAt(i)) & 0xDC00) != 0xDC00)
                    {
                        throw new IllegalArgumentException("String contains invalid Unicode code points");
                    }

                    c = 0x010000 + ((c & 0x03FF) << 10) + (low & 0x03FF);

                    bytes[j++] = (byte) (0xF0 | ((c >> 18) & 0x07));
                    bytes[j++] = (byte) (0x80 | ((c >> 12) & 0x3F));
                    bytes[j++] = (byte) (0x80 | ((c >> 6) & 0x3F));
                    bytes[j++] = (byte) (0x80 | (c & 0x3F));
                }
            }
        }
        return bytes;
    }

    public static int getUTF8Length(CharSequence string)
    {
        int size = 0;
        if(string != null)
        {
            int c;

            final int inputLength = string.length();
            for (int i = 0; i < inputLength; i++)
            {
                c = string.charAt(i);
                if ((c & 0xFF80) == 0)          /* U+0000..U+007F */
                {
                    size++;
                }
                else if ((c & 0xF800) == 0)     /* U+0080..U+07FF */
                {
                    size += 2;
                }
                else if ((c & 0xD800) != 0xD800 || (c > 0xDBFF))     /* U+0800..U+FFFF - excluding surrogate pairs */
                {
                    size += 3;
                }
                else
                {
                    if ((++i == size) || (string.charAt(i) & 0xDC00) != 0xDC00)
                    {
                        throw new IllegalArgumentException("String contains invalid Unicode code points");
                    }

                    size += 4;
                }
            }

        }
        return size;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy