Skip to content

Commit

Permalink
mojo: Add maps to java bindings.
Browse files Browse the repository at this point in the history
BUG=413863
R=ppi@chromium.org,erg@chromium.org

Review URL: https://codereview.chromium.org/648683003

Cr-Commit-Position: refs/heads/master@{#299295}
  • Loading branch information
qsr authored and Commit bot committed Oct 13, 2014
1 parent 98ff22a commit a456ad3
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package org.chromium.mojo.bindings;

import org.chromium.mojo.bindings.Struct.DataHeader;
import org.chromium.mojo.system.AsyncWaiter;
import org.chromium.mojo.system.Handle;

Expand All @@ -29,16 +30,14 @@ public class BindingsHelper {
public static final int POINTER_SIZE = 8;

/**
* The value used for the expected length of a non-fixed size array.
* The header for a serialized map element.
*/
public static final int UNSPECIFIED_ARRAY_LENGTH = -1;
public static final DataHeader MAP_STRUCT_HEADER = new DataHeader(24, 2);

/**
* Align |size| on {@link BindingsHelper#ALIGNMENT}.
* The value used for the expected length of a non-fixed size array.
*/
public static int align(int size) {
return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
}
public static final int UNSPECIFIED_ARRAY_LENGTH = -1;

/**
* Passed as |arrayNullability| when neither the array nor its elements are nullable.
Expand All @@ -63,6 +62,13 @@ 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}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,21 @@ public DataHeader readDataHeaderForPointerArray(int expectedLength) {
return readDataHeaderForArray(8, expectedLength);
}

/**
* Deserializes a {@link DataHeader} at the given offset and checks if it is correct for a map.
*/
public void readDataHeaderForMap() {
DataHeader si = readDataHeader();
if (si.size != BindingsHelper.MAP_STRUCT_HEADER.size) {
throw new DeserializationException(
"Incorrect header for map. The size is incorrect.");
}
if (si.numFields != BindingsHelper.MAP_STRUCT_HEADER.numFields) {
throw new DeserializationException(
"Incorrect header for map. The number of fields is incorrect.");
}
}

/**
* Deserializes a byte at the given offset.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ public <T extends Interface> void encode(T[] v, int offset, int arrayNullability
}
}

public Encoder encoderForMap(int offset) {
encodePointerToNextUnclaimedData(offset);
return getEncoderAtDataOffset(BindingsHelper.MAP_STRUCT_HEADER);
}

/**
* Encodes an array of {@link InterfaceRequest}.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,68 @@
{% from "constant_definition.tmpl" import constant_def %}
{% from "enum_definition.tmpl" import enum_def %}

{%- macro array_expected_length(kind) -%}
{%- if kind|is_fixed_array_kind -%}
{{kind.length}}
{%- else -%}
org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
{%- endif -%}
{%- endmacro -%}

{% macro encode(variable, kind, offset, bit, level=0) %}
{% if kind|is_pointer_array_kind %}
{% set sub_kind = kind.kind %}
if ({{variable}} == null) {
encoder{{level}}.encodeNullPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}});
} else {
org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{array_expected_length(kind)}});
org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{kind|array_expected_length}});
for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) {
{{encode(variable~'[i'~level~']', sub_kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~level, 0, level+1)|indent(8)}}
}
}
{% elif kind|is_map_kind %}
if ({{variable}} == null) {
encoder{{level}}.encodeNullPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}});
} else {
org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encoderForMap({{offset}});
int size{{level}} = {{variable}}.size();
{{kind.key_kind|java_type}}[] keys{{level}} = {{kind.key_kind|array|new_array('size'~level)}};
{{kind.value_kind|java_type}}[] values{{level}} = {{kind.value_kind|array|new_array('size'~level)}};
int index{{level}} = 0;
for (java.util.Map.Entry<{{kind.key_kind|java_type(true)}}, {{kind.value_kind|java_type(true)}}> entry{{level}} : {{variable}}.entrySet()) {
keys{{level}}[index{{level}}] = entry{{level}}.getKey();
values{{level}}[index{{level}}] = entry{{level}}.getValue();
}
{{encode('keys'~level, kind.key_kind|array, 'DataHeader.HEADER_SIZE', 0, level+1)|indent(4)}}
{{encode('values'~level, kind.value_kind|array, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE', 0, level+1)|indent(4)}}
}
{% else %}
encoder{{level}}.{{kind|encode_method(variable, offset, bit)}};
{% endif %}
{% endmacro %}

{% macro decode(variable, kind, offset, bit, level=0) %}
{% if kind|is_struct_kind or kind|is_pointer_array_kind %}
{% if kind|is_struct_kind or kind|is_pointer_array_kind or kind|is_map_kind %}
org.chromium.mojo.bindings.Decoder decoder{{level+1}} = decoder{{level}}.readPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}});
{% if kind|is_struct_kind %}
{{variable}} = {{kind|java_type}}.decode(decoder{{level+1}});
{% else %}{# kind|is_pointer_array_kind #}
{% else %}{# kind|is_pointer_array_kind or is_map_kind #}
if (decoder{{level+1}} == null) {
{{variable}} = null;
} else {
DataHeader si{{level+1}} = decoder{{level+1}}.readDataHeaderForPointerArray({{array_expected_length(kind)}});
{% if kind|is_map_kind %}
decoder{{level+1}}.readDataHeaderForMap();
{{kind.key_kind|java_type}}[] keys{{level}};
{{kind.value_kind|java_type}}[] values{{level}};
{
{{decode('keys'~level, kind.key_kind|array, 'DataHeader.HEADER_SIZE', 0, level+1)|indent(8)}}
}
{
{{decode('values'~level, kind.value_kind|array('keys'~level~'.length'), 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE', 0, level+1)|indent(8)}}
}
{{variable}} = new java.util.HashMap<{{kind.key_kind|java_type(true)}}, {{kind.value_kind|java_type(true)}}>();
for (int index{{level}} = 0; index{{level}} < keys{{level}}.length; ++index{{level}}) {
{{variable}}.put(keys{{level}}[index{{level}}], values{{level}}[index{{level}}]);
}
{% else %}
DataHeader si{{level+1}} = decoder{{level+1}}.readDataHeaderForPointerArray({{kind|array_expected_length}});
{{variable}} = {{kind|new_array('si'~(level+1)~'.numFields')}};
for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numFields; ++i{{level+1}}) {
{{decode(variable~'[i'~(level+1)~']', kind.kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~(level+1), 0, level+1)|indent(8)}}
}
{% endif %}
}
{% endif %}
{% else %}
Expand Down
27 changes: 22 additions & 5 deletions mojo/public/tools/bindings/generators/mojom_java_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,7 @@ def AppendEncodeDecodeParams(initial_params, context, kind, bit):
else:
params.append(GetJavaTrueFalse(mojom.IsNullableKind(kind)))
if mojom.IsAnyArrayKind(kind):
if mojom.IsFixedArrayKind(kind):
params.append(str(kind.length))
else:
params.append(
'org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH');
params.append(GetArrayExpectedLength(kind))
if mojom.IsInterfaceKind(kind):
params.append('%s.MANAGER' % GetJavaType(context, kind))
if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
Expand Down Expand Up @@ -253,6 +249,10 @@ def GetJavaType(context, kind, boxed=False):
if mojom.IsInterfaceRequestKind(kind):
return ('org.chromium.mojo.bindings.InterfaceRequest<%s>' %
GetNameForKind(context, kind.kind))
if mojom.IsMapKind(kind):
return 'java.util.Map<%s, %s>' % (
GetBoxedJavaType(context, kind.key_kind),
GetBoxedJavaType(context, kind.value_kind))
if mojom.IsAnyArrayKind(kind):
return '%s[]' % GetJavaType(context, kind.kind)
if mojom.IsEnumKind(kind):
Expand Down Expand Up @@ -323,6 +323,20 @@ def _TranslateNamedValue(named_value):
return 'java.lang.Float.NaN'
return token

def GetArrayKind(kind, size = None):
if size is None:
return mojom.Array(kind)
else:
array = mojom.FixedArray(0, kind)
array.java_map_size = size
return array

def GetArrayExpectedLength(kind):
if mojom.IsFixedArrayKind(kind):
return getattr(kind, 'java_map_size', str(kind.length))
else:
return 'org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH'

def IsPointerArrayKind(kind):
if not mojom.IsAnyArrayKind(kind):
return False
Expand Down Expand Up @@ -379,6 +393,8 @@ def ZipContentInto(root, zip_filename):
class Generator(generator.Generator):

java_filters = {
'array': GetArrayKind,
'array_expected_length': GetArrayExpectedLength,
'interface_response_name': GetInterfaceResponseName,
'constant_value': ConstantValue,
'default_value': DefaultValue,
Expand All @@ -389,6 +405,7 @@ class Generator(generator.Generator):
'has_method_without_response': HasMethodWithoutResponse,
'is_fixed_array_kind': mojom.IsFixedArrayKind,
'is_handle': mojom.IsNonInterfaceHandleKind,
'is_map_kind': mojom.IsMapKind,
'is_nullable_kind': mojom.IsNullableKind,
'is_pointer_array_kind': IsPointerArrayKind,
'is_struct_kind': mojom.IsStructKind,
Expand Down

0 comments on commit a456ad3

Please sign in to comment.