private Object extractOne()

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;
    }