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

org.robovm.rt.bro.ptr.BytePtr Maven / Gradle / Ivy

/*
 * Copyright (C) 2012 Trillian Mobile AB
 *
 * Licensed 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.robovm.rt.bro.ptr;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import org.robovm.rt.VM;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.annotation.StructMember;

/**
 * Points to an 8-bit signed value (char * in C).
 */
public final class BytePtr extends Struct {
    
    /**
     * Pointer to {@link BytePtr} (char ** in C)
     */
    public static class BytePtrPtr extends org.robovm.rt.bro.ptr.Ptr {}
    
    /**
     * Creates a new {@link BytePtr} with a value of 0.
     */
    public BytePtr() {
    }
    
    /**
     * Creates a new {@link BytePtr} and initializes it with the specified value.
     * 
     * @param value the value.
     */
    public BytePtr(byte value) {
        set(value);
    }

    /**
     * Returns the current value.
     * 
     * @return the value.
     */
    @StructMember(0)
    public native byte get();
    
    /**
     * Sets the value.
     * 
     * @param value the new value.
     */
    @StructMember(0)
    public native void set(byte value);
    
    /**
     * Returns a {@link String} created from the NUL-terminated C string pointed 
     * to by this {@link BytePtr}. Non ASCII characters will be replaced with 
     * '?' in the result. This method is more efficient than using 
     * {@link #toStringZ(Charset)} with ASCII as {@link Charset}.
     * 
     * @return a {@link String} containing the same characters as the C string 
     *         pointed to.
     */
    public String toStringAsciiZ() {
        int length = 0;
        int b = 0;
        long address = getHandle();
        while ((b = VM.getByte(address++)) != 0) {
            length++;
        }
        StringBuilder sb = new StringBuilder(length);
        address = getHandle();
        while ((b = VM.getByte(address++)) != 0) {
            if (b < 0x80) {
                sb.append((char) b);
            } else {
                sb.append('?');
            }
        }
        return sb.toString();
    }
    
    /**
     * Returns a {@link String} created from the NUL-terminated C string pointed 
     * to by this {@link BytePtr} using the default {@link Charset}. Illegal 
     * characters will be replaced with '?' in the result. This assumes that
     * the default {@link Charset} is an 8-bit encoding or a variable length
     * encoding with 8-bits as smallest bit length such as UTF-8.
     * 
     * @return a {@link String} converted from the C string bytes.
     */
    public String toStringZ() {
        return toStringZ(Charset.defaultCharset());
    }
    
    /**
     * Returns a {@link String} created from the NUL-terminated C string pointed 
     * to by this {@link BytePtr} using the specified {@link Charset}. Illegal 
     * characters will be replaced with '?' in the result.
     * 
     * @param charset the {@link Charset} to use. Must be an 8-bit or variable
     *        length character encoding with 8-bits as smallest value and that 
     *        can be NUL-terminated (e.g. UTF-8).
     * @return a {@link String} converted from the C string bytes.
     */
    public String toStringZ(Charset charset) {
        int length = 0;
        long address = getHandle();
        while (VM.getByte(address++) != 0) {
            length++;
        }
        return charset.decode(asByteBuffer(length)).toString();
    }
    
    /**
     * Returns a {@link ByteBuffer} which reads and writes to the same memory
     * location pointed to by this {@link BytePtr}.
     * 
     * @param n the maximum number of bytes the {@link ByteBuffer} can 
     *        read/write. This will be the {@link ByteBuffer}'s 
     *        capacity.
     * @return the {@link ByteBuffer}.
     */
    public ByteBuffer asByteBuffer(int n) {
        return VM.newDirectByteBuffer(getHandle(), n);
    }
    
    /**
     * Copies {@code n} bytes from the memory pointed to by this {@link BytePtr}
     * to a new {@code byte[]} instance.
     * 
     * @param n the number of bytes to copy.
     * @return the {@code byte[]}.
     */
    public byte[] toByteArray(int n) {
        byte[] result = new byte[n];
        get(result);
        return result;
    }

    /**
     * Copies {@code dst.length} bytes from the memory pointed to by this 
     * {@link BytePtr} to {@code dst}.
     * 
     * @param dst the destination.
     */
    public void get(byte[] dst) {
        get(dst, 0, dst.length);
    }

    /**
     * Copies {@code count} bytes from the memory pointed to by this 
     * {@link BytePtr} to {@code dst} starting at offset {@code offset}.
     * 
     * @param dst the destination.
     * @param offset the offset within the destination array to start copying to.
     * @param count the number of elements to copy.
     */
    public void get(byte[] dst, int offset, int count) {
        asByteBuffer(count).get(dst, offset, count);
    }

    /**
     * Copies {@code src.length} bytes from {@code src} to the memory pointed to by
     * this {@link BytePtr}.
     * 
     * @param src the source.
     */
    public void set(byte[] src) {
        set(src, 0, src.length);
    }
    
    /**
     * Copies {@code count} bytes from {@code src} starting at offset {@code offset}
     * to the memory pointed to by this {@link BytePtr}.
     * 
     * @param src the source.
     * @param offset the offset within the source array to start copying from.
     * @param count the number of elements to copy.
     */
    public void set(byte[] src, int offset, int count) {
        asByteBuffer(count).put(src, offset, count);
    }
    
    /**
     * Converts the specified {@link String} to a NUL-terminated C string of 
     * ASCII characters. Non ASCII characters will be replaced with '?' in the 
     * result. The memory will be allocated on the GCed heaped. This method is 
     * more efficient than using {@link #toStringZ(Charset)} with ASCII as 
     * {@link Charset}.
     * 
     * @param s the {@link String} to convert.
     * @return a {@link BytePtr} which points to the first character in the result.
     */
    public static BytePtr toBytePtrAsciiZ(String s) {
        return toBytePtrAsciiZ(s, false);
    }
    
    /**
     * Converts the specified {@link String} to a NUL-terminated C string of 
     * ASCII characters. Non ASCII characters will be replaced with '?' in the 
     * result. This method is more efficient than using 
     * {@link #toStringZ(Charset)} with ASCII as {@link Charset}.
     * 
     * @param s the {@link String} to convert.
     * @param useNativeHeap whether the memory should be allocated on the native 
     *        heap using {@code malloc()} or on the GCed heap.
     * @return a {@link BytePtr} which points to the first character in the result.
     */
    public static BytePtr toBytePtrAsciiZ(String s, boolean useNativeHeap) {
        int length = s.length();
        long handle = useNativeHeap ? VM.malloc(length + 1) : VM.allocateMemoryAtomic(length + 1);
        long address = handle;
        for (int i = 0; i < length; i++) {
            char c = s.charAt(i);
            if (c < 0x80) {
                VM.setByte(address, (byte) c);
            } else {
                VM.setByte(address, (byte) '?');
            }
            address++;
        }
        // VM.malloc() and VM.allocateMemoryAtomic() initialize the memory with 
        // zeroes so there's no need to set the NUL-terminator.
        return Struct.toStruct(BytePtr.class, handle);
    }
    
    /**
     * Converts the specified {@link String} to a NUL-terminated C string using
     * the default {@link Charset}. Illegal characters will be replaced with 
     * '?' in the result. The memory will be allocated on the GCed heaped.
     * This assumes that the default {@link Charset} is an 8-bit encoding or a
     * variable length encoding with 8-bits as smallest bit length such as 
     * UTF-8.
     * 
     * @param s the {@link String} to convert.
     * @return a {@link BytePtr} which points to the first character in the result.
     */
    public static BytePtr toBytePtrZ(String s) {
        return toBytePtrZ(s, Charset.defaultCharset(), false);
    }
    
    /**
     * Converts the specified {@link String} to a NUL-terminated C string using
     * the specified {@link Charset}. Illegal characters will be replaced with 
     * '?' in the result. The memory will be allocated on the GCed heaped.
     * 
     * @param s the {@link String} to convert.
     * @param charset the {@link Charset} to use. Must be an 8-bit or variable
     *        length character encoding with 8-bits as smallest value and that 
     *        can be NUL-terminated (e.g. UTF-8).
     * @return a {@link BytePtr} which points to the first character in the result.
     */
    public static BytePtr toBytePtrZ(String s, Charset charset) {
        return toBytePtrZ(s, charset, false);
    }
    
    /**
     * Converts the specified {@link String} to a NUL-terminated C string using
     * the specified {@link Charset}. Illegal characters will be replaced with 
     * '?' in the result.
     * 
     * @param s the {@link String} to convert.
     * @param charset the {@link Charset} to use. Must be an 8-bit or variable
     *        length character encoding with 8-bits as smallest value and that 
     *        can be NUL-terminated (e.g. UTF-8).
     * @param useNativeHeap whether the memory should be allocated on the native 
     *        heap using {@code malloc()} or on the GCed heap.
     * @return a {@link BytePtr} which points to the first character in the result.
     */
    public static BytePtr toBytePtrZ(String s, Charset charset, boolean useNativeHeap) {
        byte[] bytes = s.getBytes(charset);
        int length = bytes.length;
        long handle = useNativeHeap ? VM.malloc(length + 1) : VM.allocateMemoryAtomic(length + 1);
        VM.memcpy(handle, VM.getArrayValuesAddress(bytes), length);
        // VM.malloc() and VM.allocateMemoryAtomic() initialize the memory with 
        // zeroes so there's no need to set the NUL-terminator.
        return Struct.toStruct(BytePtr.class, handle);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy