// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.mojo.bindings;
import org.chromium.mojo.system.Handle;
import org.chromium.mojo.system.Watcher;
/** Helper functions. */
public class BindingsHelper {
/** Alignment in bytes for mojo serialization. */
public static final int ALIGNMENT = 8;
/**
* The size, in bytes, of a serialized handle. A handle is serialized as an int representing the
* offset of the handle in the list of handles.
*/
public static final int SERIALIZED_HANDLE_SIZE = 4;
/**
* The size, in bytes, of a serialized interface, which consists of a serialized handle (4
* bytes) and a version number (4 bytes).
*/
public static final int SERIALIZED_INTERFACE_SIZE = 8;
/**
* The size, in bytes, of a serialized pointer. A pointer is serializaed as an unsigned long
* representing the offset from its position to the pointed elemnt.
*/
public static final int POINTER_SIZE = 8;
/** The size, in bytes, of a serialized union. */
public static final int UNION_SIZE = 16;
/** The header for a serialized map element. */
public static final DataHeader MAP_STRUCT_HEADER = new DataHeader(24, 0);
/** The value used for the expected length of a non-fixed size array. */
public static final int UNSPECIFIED_ARRAY_LENGTH = -1;
/** Passed as |arrayNullability| when neither the array nor its elements are nullable. */
public static final int NOTHING_NULLABLE = 0;
/** "Array bit" of |arrayNullability| is set iff the array itself is nullable. */
public static final int ARRAY_NULLABLE = (1 << 0);
/** "Element bit" of |arrayNullability| is set iff the array elements are nullable. */
public static final int ELEMENT_NULLABLE = (1 << 1);
public static boolean isArrayNullable(int arrayNullability) {
return (arrayNullability & ARRAY_NULLABLE) > 0;
}
public static boolean isElementNullable(int arrayNullability) {
return (arrayNullability & ELEMENT_NULLABLE) > 0;
}
/** Align |size| on {@link BindingsHelper#ALIGNMENT}. */
public static int align(int size) {
return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
}
/** Align |size| on {@link BindingsHelper#ALIGNMENT}. */
public static long align(long size) {
return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
}
/** Compute the size in bytes of the given string encoded as utf8. */
public static int utf8StringSizeInBytes(String s) {
int res = 0;
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
int codepoint = c;
if (isSurrogate(c)) {
i++;
char c2 = s.charAt(i);
codepoint = Character.toCodePoint(c, c2);
}
res += 1;
if (codepoint > 0x7f) {
res += 1;
if (codepoint > 0x7ff) {
res += 1;
if (codepoint > 0xffff) {
res += 1;
if (codepoint > 0x1fffff) {
res += 1;
if (codepoint > 0x3ffffff) {
res += 1;
}
}
}
}
}
}
return res;
}
/** Computes the size needed to represent |numElements|, aligned to |alignmentBytes|. */
public static int computeBitfieldSize(long alignmentBytes, int numElements) {
// Math must be in long to ensure that we do not overflow.
long alignmentBits = alignmentBytes * 8;
return (int) (((numElements + alignmentBits - 1) / alignmentBits) * alignmentBytes);
}
/** Returns |true| if and only if the two objects are equals, handling |null|. */
public static boolean equals(Object o1, Object o2) {
if (o1 == o2) {
return true;
}
if (o1 == null) {
return false;
}
return o1.equals(o2);
}
/** Returns the hash code of the object, handling |null|. */
public static int hashCode(Object o) {
if (o == null) {
return 0;
}
return o.hashCode();
}
/** Returns the hash code of the value. */
public static int hashCode(boolean o) {
return o ? 1231 : 1237;
}
/** Returns the hash code of the value. */
public static int hashCode(long o) {
return (int) (o ^ (o >>> 32));
}
/** Returns the hash code of the value. */
public static int hashCode(float o) {
return Float.floatToIntBits(o);
}
/** Returns the hash code of the value. */
public static int hashCode(double o) {
return hashCode(Double.doubleToLongBits(o));
}
/** Returns the hash code of the value. */
public static int hashCode(int o) {
return o;
}
/**
* Determines if the given {@code char} value is a Unicode <i>surrogate code unit</i>. See
* {@link Character#isSurrogate}. Extracting here because the method only exists at API level
* 19.
*/
private static boolean isSurrogate(char c) {
return c >= Character.MIN_SURROGATE && c < (Character.MAX_SURROGATE + 1);
}
/**
* Returns an {@link AsyncWaiter} to use with the given handle, or |null| if none if available.
*/
static Watcher getWatcherForHandle(Handle handle) {
if (handle.getCore() != null) {
return handle.getCore().getWatcher();
} else {
return null;
}
}
}