/* * Copyright (c) Daniel Reichhard, daniel.reichhard@gmail.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Daniel Reichhard * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /** * This is the data-marshalling class for primitive xdr-types */ package ejip.nfs; /** * @author Daniel Reichhard * */ public class Xdr { /** * read an integer at position n (non-consuming) * * @param dataBuffer * the buffer to read from * @param n * the position in the buffer * @return the integer */ public static int getIntAt(StringBuffer dataBuffer, int n) { int retval; if (((dataBuffer.length() - (4 * n)) / 4) > 0) { retval = dataBuffer.charAt(4 * n + 3) | dataBuffer.charAt(4 * n + 2) << 8 | dataBuffer.charAt(4 * n + 1) << 16 | dataBuffer.charAt(4 * n) << 24; return retval; } return 0; // error return value } /** * get next integer out of the <code>dataBuffer</code> (and consume it) * * @param dataBuffer * the buffer to read from * @return the integer */ public static int getNextInt(StringBuffer dataBuffer) { int retval; retval = getIntAt(dataBuffer, 0); dataBuffer.delete(0, 4); return retval; } public static long getNextLong(StringBuffer dataBuffer) { long retval; retval = getIntAt(dataBuffer, 0) << 32 | getIntAt(dataBuffer, 1); dataBuffer.delete(0, 8); return retval; } public static void getBytes(StringBuffer dataBuffer, StringBuffer targetBuffer, int size) { int fillBytes; if ((size > 0) & (dataBuffer.length() >= size)) { for (int i = 0; i < size; i++) { targetBuffer.append(dataBuffer.charAt(i)); } fillBytes = 4 - (size % 4); if (fillBytes != 4) { size += fillBytes; } dataBuffer.delete(0, size); } } /** * get next string out of the <code>dataBuffer</code> (and consume it) * * @param dataBuffer * the buffer to read from * @return the string */ public static void getNextStringBuffer(StringBuffer dataBuffer, StringBuffer targetBuffer) { int length; length = Xdr.getNextInt(dataBuffer); if (targetBuffer == null) { dataBuffer.delete(0, length); } else { targetBuffer.setLength(0); getBytes(dataBuffer, targetBuffer, length); } } /** * append an integer to the <code>dataBuffer</code> * * @param dataBuffer * the buffer to appended to * @param i * the integer to append */ public static void append(StringBuffer dataBuffer, int i) { // if (i <= 0x7FFFFFFF) { dataBuffer.append((char) ((i & 0xFF000000) >>> 24)); dataBuffer.append((char) ((i & 0xFF0000) >> 16)); dataBuffer.append((char) ((i & 0xFF00) >> 8)); dataBuffer.append((char) ((i & 0xFF))); // return true; // } else { // return false; // } } /** * append a long integer to the <code>dataBuffer</code> * * @param dataBuffer * the buffer to appended to * @param i * the long integer to append */ public static void append(StringBuffer dataBuffer, long i) { // if (i <= 0x7FFFFFFF) { dataBuffer.append((char) ((i >>> 56) & 0xFF)); dataBuffer.append((char) ((i >> 48) & 0xFF)); dataBuffer.append((char) ((i >> 40) & 0xFF)); dataBuffer.append((char) ((i >> 32) & 0xFF)); dataBuffer.append((char) ((i >> 24) & 0xFF)); dataBuffer.append((char) ((i >> 16) & 0xFF)); dataBuffer.append((char) ((i >> 8) & 0xFF)); dataBuffer.append((char) (i & 0xFF)); // return true; // } else { // return false; // } } /** * append an integer array to the <code>dataBuffer</code> * * @param dataBuffer * the buffer to appended to * @param i * the integer array to append */ public static void append(StringBuffer dataBuffer, int[] i) { for (int j = 0; j < i.length; j++) { if (i[j] == 0) { Xdr.append(dataBuffer, j); j = i.length; } } for (int j = 0; j < i.length; j++) { if (i[j] != 0) { // TODO: is 0 a valid group? Xdr.append(dataBuffer, i[j]); } } } /** * append a StringBuffer s to the <code>dataBuffer</code> * * @param dataBuffer * the buffer to appended to * @param s * the String to append */ public static void append(StringBuffer dataBuffer, StringBuffer s) { Xdr.append(dataBuffer, s.length()); Xdr.appendRaw(dataBuffer, s); } /** * append a StringBuffer as Opaque with fixed size * * @param dataBuffer * @param s */ public static void appendRaw(StringBuffer dataBuffer, StringBuffer s) { int rest; for (int i = 0; i < s.length(); i++) { //@WCA loop=9 dataBuffer.append(s.charAt(i)); } rest = 4 - (s.length() % 4); while ((rest != 4) & (rest > 0)) { //@WCA loop<=3 dataBuffer.append((char) 0); rest--; } } }