/* This file is part of GNUnet. Copyright (C) 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.gnunet.construct.parsers; import org.gnunet.construct.Message; import org.gnunet.construct.ReflectUtil; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.nio.ByteBuffer; import java.util.List; public class IntegerFillParser implements Parser { private final Field targetField; private final boolean signed; private final int byteSize; public IntegerFillParser(Field targetField, boolean signed, int byteSize) { this.targetField = targetField; this.signed = signed; this.byteSize = byteSize; } @Override public int getSize(Message srcObj) { final Object arr = ReflectUtil.justGet(srcObj, targetField); if (arr == null) { throw new RuntimeException("array not initialized"); } return byteSize * Array.getLength(arr); } @Override public int parse(ByteBuffer srcBuf, int frameStart, Message frameObj, Message dstObj, List frameSizePath) { if (frameSizePath == null) { throw new AssertionError("IntegerFillParser expects a non-null frameSizePath. Did you specify a @FrameSize field?"); } final int frameSize = ReflectUtil.justGetInt(frameObj, frameSizePath); int remaining = frameStart + frameSize - srcBuf.position(); int elemNumber = remaining / byteSize; @SuppressWarnings("unchecked") final Class arrayElementType = (Class) targetField.getType().getComponentType(); if (!arrayElementType.isPrimitive()) { throw new AssertionError("IntegerFillParser is expected to be of primitive type, not " + arrayElementType); } final Object arr = Array.newInstance(arrayElementType, elemNumber); ReflectUtil.justSet(dstObj, targetField, arr); for (int i = 0; i < elemNumber; ++i) { long v = IntegerUtil.readLong(srcBuf, signed, byteSize); ReflectUtil.justSetArray(arr, i, v); } return remaining; } @Override public int write(ByteBuffer dstBuf, Message srcObj) { final Object arr = ReflectUtil.justGet(srcObj, targetField); if (arr == null) { throw new RuntimeException("array not initialized"); } for (int i = 0; i < Array.getLength(arr); ++i) { IntegerUtil.writeLong(Array.getLong(arr, i), dstBuf, signed, byteSize); } return getSize(srcObj); } @Override public void patch(Message m, int frameSize, List frameSizePath, Message frameObj) { if (frameSizePath == null) { throw new AssertionError("IntegerFillParser expects a non-null frameSizePath. Did you specify a @FrameSize field?"); } ReflectUtil.justSetInt(frameObj, frameSizePath, frameSize); } @Override public int getStaticSize() { // not known return 0; } }