in dbus-java/src/main/java/org/freedesktop/dbus/messages/Message.java [524:770]
private int appendone(byte[] sigb, int sigofs, Object data) throws DBusException {
try {
int i = sigofs;
logger.trace("{}", bytecounter);
logger.trace("Appending type: {} value: {}", ((char) sigb[i]), data);
// pad to the alignment of this type.
pad(sigb[i]);
switch (sigb[i]) {
case ArgumentType.BYTE:
appendByte(((Number) data).byteValue());
break;
case ArgumentType.BOOLEAN:
appendint(((Boolean) data).booleanValue() ? 1 : 0, 4);
break;
case ArgumentType.DOUBLE:
long l = Double.doubleToLongBits(((Number) data).doubleValue());
appendint(l, 8);
break;
case ArgumentType.FLOAT:
int rf = Float.floatToIntBits(((Number) data).floatValue());
appendint(rf, 4);
break;
case ArgumentType.UINT32:
appendint(((Number) data).longValue(), 4);
break;
case ArgumentType.INT64:
appendint(((Number) data).longValue(), 8);
break;
case ArgumentType.UINT64:
if (big) {
appendint(((UInt64) data).top(), 4);
appendint(((UInt64) data).bottom(), 4);
} else {
appendint(((UInt64) data).bottom(), 4);
appendint(((UInt64) data).top(), 4);
}
break;
case ArgumentType.INT32:
appendint(((Number) data).intValue(), 4);
break;
case ArgumentType.UINT16:
appendint(((Number) data).intValue(), 2);
break;
case ArgumentType.INT16:
appendint(((Number) data).shortValue(), 2);
break;
case ArgumentType.FILEDESCRIPTOR:
filedescriptors.add((FileDescriptor)data);
appendint(filedescriptors.size() - 1, 4);
logger.debug( "Just inserted {} as filedescriptor", filedescriptors.size() - 1 );
break;
case ArgumentType.STRING:
case ArgumentType.OBJECT_PATH:
// Strings are marshalled as a UInt32 with the length,
// followed by the String, followed by a null byte.
String payload = data.toString();
byte[] payloadbytes = null;
try {
payloadbytes = payload.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
logger.debug("System does not support UTF-8 encoding", uee);
throw new DBusException("System does not support UTF-8 encoding");
}
logger.trace("Appending String of length {}", payloadbytes.length);
appendint(payloadbytes.length, 4);
appendBytes(payloadbytes);
appendBytes(padding[1]);
// pad(ArgumentType.STRING);? do we need this?
break;
case ArgumentType.SIGNATURE:
// Signatures are marshalled as a byte with the length,
// followed by the String, followed by a null byte.
// Signatures are generally short, so preallocate the array
// for the string, length and null byte.
if (data instanceof Type[]) {
payload = Marshalling.getDBusType((Type[]) data);
} else {
payload = (String) data;
}
byte[] pbytes = payload.getBytes();
preallocate(2 + pbytes.length);
appendByte((byte) pbytes.length);
appendBytes(pbytes);
appendByte((byte) 0);
break;
case ArgumentType.ARRAY:
// Arrays are given as a UInt32 for the length in bytes,
// padding to the element alignment, then elements in
// order. The length is the length from the end of the
// initial padding to the end of the last element.
if (logger.isTraceEnabled()) {
if (data instanceof Object[]) {
logger.trace("Appending array: {}", Arrays.deepToString((Object[]) data));
}
}
byte[] alen = new byte[4];
appendBytes(alen);
pad(sigb[++i]);
long c = bytecounter;
// optimise primitives
if (data.getClass().isArray() && data.getClass().getComponentType().isPrimitive()) {
byte[] primbuf;
int algn = getAlignment(sigb[i]);
int len = Array.getLength(data);
switch (sigb[i]) {
case ArgumentType.BYTE:
primbuf = (byte[]) data;
break;
case ArgumentType.INT16:
case ArgumentType.INT32:
case ArgumentType.INT64:
primbuf = new byte[len * algn];
for (int j = 0, k = 0; j < len; j++, k += algn) {
marshallint(Array.getLong(data, j), primbuf, k, algn);
}
break;
case ArgumentType.BOOLEAN:
primbuf = new byte[len * algn];
for (int j = 0, k = 0; j < len; j++, k += algn) {
marshallint(Array.getBoolean(data, j) ? 1 : 0, primbuf, k, algn);
}
break;
case ArgumentType.DOUBLE:
primbuf = new byte[len * algn];
if (data instanceof float[]) {
for (int j = 0, k = 0; j < len; j++, k += algn) {
marshallint(Double.doubleToRawLongBits(((float[]) data)[j]), primbuf, k, algn);
}
} else {
for (int j = 0, k = 0; j < len; j++, k += algn) {
marshallint(Double.doubleToRawLongBits(((double[]) data)[j]), primbuf, k, algn);
}
}
break;
case ArgumentType.FLOAT:
primbuf = new byte[len * algn];
for (int j = 0, k = 0; j < len; j++, k += algn) {
marshallint(Float.floatToRawIntBits(((float[]) data)[j]), primbuf, k, algn);
}
break;
default:
throw new MarshallingException("Primitive array being sent as non-primitive array.");
}
appendBytes(primbuf);
} else if (data instanceof List) {
Object[] contents = ((List<?>) data).toArray();
int diff = i;
ensureBuffers(contents.length * 4);
for (Object o : contents) {
diff = appendone(sigb, i, o);
}
if (contents.length == 0) {
diff = EmptyCollectionHelper.determineSignatureOffsetArray(sigb, diff);
}
i = diff;
} else if (data instanceof Map) {
int diff = i;
Map<Object, Object> map = (Map<Object, Object>) data;
ensureBuffers(map.size() * 6);
for (Map.Entry<Object, Object> o : map.entrySet()) {
diff = appendone(sigb, i, o);
}
if (map.size() == 0) {
diff = EmptyCollectionHelper.determineSignatureOffsetDict(sigb, diff);
}
i = diff;
} else {
Object[] contents = (Object[]) data;
ensureBuffers(contents.length * 4);
int diff = i;
for (Object o : contents) {
diff = appendone(sigb, i, o);
}
if (contents.length == 0) {
diff = EmptyCollectionHelper.determineSignatureOffsetArray(sigb, diff);
}
i = diff;
}
logger.trace("start: {} end: {} length: {}", c, bytecounter, (bytecounter - c));
marshallint(bytecounter - c, alen, 0, 4);
break;
case ArgumentType.STRUCT1:
// Structs are aligned to 8 bytes
// and simply contain each element marshalled in order
Object[] contents;
if (data instanceof Container) {
contents = ((Container) data).getParameters();
} else {
contents = (Object[]) data;
}
ensureBuffers(contents.length * 4);
int j = 0;
for (i++; sigb[i] != ArgumentType.STRUCT2; i++) {
i = appendone(sigb, i, contents[j++]);
}
break;
case ArgumentType.DICT_ENTRY1:
// Dict entries are the same as structs.
if (data instanceof Map.Entry) {
i++;
i = appendone(sigb, i, ((Map.Entry<?, ?>) data).getKey());
i++;
i = appendone(sigb, i, ((Map.Entry<?, ?>) data).getValue());
i++;
} else {
contents = (Object[]) data;
j = 0;
for (i++; sigb[i] != ArgumentType.DICT_ENTRY2; i++) {
i = appendone(sigb, i, contents[j++]);
}
}
break;
case ArgumentType.VARIANT:
// Variants are marshalled as a signature
// followed by the value.
if (data instanceof Variant) {
Variant<?> var = (Variant<?>) data;
appendone(new byte[] {
ArgumentType.SIGNATURE
}, 0, var.getSig());
appendone((var.getSig()).getBytes(), 0, var.getValue());
} else if (data instanceof Object[]) {
contents = (Object[]) data;
appendone(new byte[] {
ArgumentType.SIGNATURE
}, 0, contents[0]);
appendone(((String) contents[0]).getBytes(), 0, contents[1]);
} else {
String sig = Marshalling.getDBusType(data.getClass())[0];
appendone(new byte[] {
ArgumentType.SIGNATURE
}, 0, sig);
appendone((sig).getBytes(), 0, data);
}
break;
}
return i;
} catch (ClassCastException cce) {
logger.debug("Trying to marshall to unconvertible type.", cce);
throw new MarshallingException(
MessageFormat.format("Trying to marshall to unconvertible type (from {0} to {1}).",
data.getClass().getName(), (char) sigb[sigofs]));
}
}