in dbus-java/src/main/java/org/freedesktop/dbus/messages/Message.java [882:1029]
private Object extractOne(byte[] _signatureBuf, byte[] _dataBuf, int[] _offsets, boolean _contained)
throws DBusException {
logger.trace("Extracting type: {} from offset {}", ((char) _signatureBuf[_offsets[OFFSET_SIG]]),
_offsets[OFFSET_DATA]);
Object rv = null;
_offsets[OFFSET_DATA] = align(_offsets[OFFSET_DATA], _signatureBuf[_offsets[OFFSET_SIG]]);
switch (_signatureBuf[_offsets[OFFSET_SIG]]) {
case ArgumentType.BYTE:
rv = _dataBuf[_offsets[OFFSET_DATA]++];
break;
case ArgumentType.UINT32:
rv = new UInt32(demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4));
_offsets[OFFSET_DATA] += 4;
break;
case ArgumentType.INT32:
rv = (int) demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
_offsets[OFFSET_DATA] += 4;
break;
case ArgumentType.INT16:
rv = (short) demarshallint(_dataBuf, _offsets[OFFSET_DATA], 2);
_offsets[OFFSET_DATA] += 2;
break;
case ArgumentType.UINT16:
rv = new UInt16((int) demarshallint(_dataBuf, _offsets[OFFSET_DATA], 2));
_offsets[OFFSET_DATA] += 2;
break;
case ArgumentType.INT64:
rv = demarshallint(_dataBuf, _offsets[OFFSET_DATA], 8);
_offsets[OFFSET_DATA] += 8;
break;
case ArgumentType.UINT64:
long top;
long bottom;
if (big) {
top = demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
_offsets[OFFSET_DATA] += 4;
bottom = demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
} else {
bottom = demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
_offsets[OFFSET_DATA] += 4;
top = demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
}
rv = new UInt64(top, bottom);
_offsets[OFFSET_DATA] += 4;
break;
case ArgumentType.DOUBLE:
long l = demarshallint(_dataBuf, _offsets[OFFSET_DATA], 8);
_offsets[OFFSET_DATA] += 8;
rv = Double.longBitsToDouble(l);
break;
case ArgumentType.FLOAT:
int rf = (int) demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
_offsets[OFFSET_DATA] += 4;
rv = Float.intBitsToFloat(rf);
break;
case ArgumentType.BOOLEAN:
rf = (int) demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
_offsets[OFFSET_DATA] += 4;
rv = (1 == rf) ? Boolean.TRUE : Boolean.FALSE;
break;
case ArgumentType.ARRAY:
long size = demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
logger.trace("Reading array of size: {}", size);
_offsets[OFFSET_DATA] += 4;
byte algn = (byte) getAlignment(_signatureBuf[++_offsets[OFFSET_SIG]]);
_offsets[OFFSET_DATA] = align(_offsets[OFFSET_DATA], _signatureBuf[_offsets[OFFSET_SIG]]);
int length = (int) (size / algn);
if (length > AbstractConnection.MAX_ARRAY_LENGTH) {
throw new MarshallingException("Arrays must not exceed " + AbstractConnection.MAX_ARRAY_LENGTH);
}
rv = optimizePrimitives(_signatureBuf, _dataBuf, _offsets, size, algn, length);
if (_contained && !(rv instanceof List) && !(rv instanceof Map)) {
rv = ArrayFrob.listify(rv);
}
break;
case ArgumentType.STRUCT1:
List<Object> contents = new ArrayList<>();
while (_signatureBuf[++_offsets[OFFSET_SIG]] != ArgumentType.STRUCT2) {
contents.add(extractOne(_signatureBuf, _dataBuf, _offsets, true));
}
rv = contents.toArray();
break;
case ArgumentType.DICT_ENTRY1:
Object[] decontents = new Object[2];
if(logger.isTraceEnabled()) { // avoid allocating these large heapdumps when trace logging is disabled
logger.trace("Extracting Dict Entry ({}) from: {}",
Hexdump.toAscii(_signatureBuf, _offsets[OFFSET_SIG], _signatureBuf.length - _offsets[OFFSET_SIG]),
Hexdump.toHex(_dataBuf, _offsets[OFFSET_DATA], _dataBuf.length - _offsets[OFFSET_DATA]));
}
_offsets[OFFSET_SIG]++;
decontents[0] = extractOne(_signatureBuf, _dataBuf, _offsets, true);
_offsets[OFFSET_SIG]++;
decontents[1] = extractOne(_signatureBuf, _dataBuf, _offsets, true);
_offsets[OFFSET_SIG]++;
rv = decontents;
break;
case ArgumentType.VARIANT:
int[] newofs = new int[] {
0, _offsets[OFFSET_DATA]
};
String sig = (String) extract(ArgumentType.SIGNATURE_STRING, _dataBuf, newofs)[0];
newofs[OFFSET_SIG] = 0;
rv = new Variant<>(extract(sig, _dataBuf, newofs)[0], sig);
_offsets[OFFSET_DATA] = newofs[OFFSET_DATA];
break;
case ArgumentType.FILEDESCRIPTOR:
rv = filedescriptors.get((int)demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4));
_offsets[OFFSET_DATA] += 4;
break;
case ArgumentType.STRING:
length = (int) demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
_offsets[OFFSET_DATA] += 4;
try {
rv = new String(_dataBuf, _offsets[OFFSET_DATA], length, "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");
}
_offsets[OFFSET_DATA] += length + 1;
break;
case ArgumentType.OBJECT_PATH:
length = (int) demarshallint(_dataBuf, _offsets[OFFSET_DATA], 4);
_offsets[OFFSET_DATA] += 4;
rv = new ObjectPath(getSource(), new String(_dataBuf, _offsets[OFFSET_DATA], length));
_offsets[OFFSET_DATA] += length + 1;
break;
case ArgumentType.SIGNATURE:
length = (_dataBuf[_offsets[OFFSET_DATA]++] & 0xFF);
rv = new String(_dataBuf, _offsets[OFFSET_DATA], length);
_offsets[OFFSET_DATA] += length + 1;
break;
default:
throw new UnknownTypeCodeException(_signatureBuf[_offsets[OFFSET_SIG]]);
}
if (logger.isTraceEnabled()) {
if (rv instanceof Object[]) {
logger.trace("Extracted: {} (now at {})", Arrays.deepToString((Object[]) rv), _offsets[OFFSET_DATA]);
} else {
logger.trace("Extracted: {} (now at {})", rv, _offsets[OFFSET_DATA]);
}
}
return rv;
}