/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2003-2004 Pierre G. Richard * * Copyright (C) 2003-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine 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. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.net; // this should better go into a kinda util pkg. import totalcross.sys.Vm; /** * String of bytes. Used by the Network classes to avoid converting the byte array * received from a Socket into Strings. */ public class ByteString { protected byte[] base; protected int pos; protected int len; /** * Constructor * <P> * <B>Warning:</B> * This constructor is not equivalent to a String constructor.  * The caller must ensure the byte array will never be changed after * this constructor is called. * * @param start where this ByteString starts in the byte array * @param len length of this ByteString * @param base byte array that holds this ByteString * @see ByteString#ByteString(byte[] base, int pos, int len) if * you want a safe constructor. */ ByteString(int pos, int len, byte[] base) { this.base = base; this.pos = pos; this.len = len; } /** * Safe constructor for a ByteString (but slower and also uses more memory). * * @param base byte array that holds this ByteString * @param start where this ByteString starts in the byte array * @param len length of this ByteString */ ByteString(byte[] base, int pos, int len) { this.base = new byte[len]; Vm.arrayCopy(base, pos, this.base, 0, len); this.pos = 0; this.len = len; } /** * Copy - if the source is null, this returns null. * Otherwise, the ByteString is copied. * * @param source ByteString to be copied */ public static ByteString copy(ByteString source) { if (source == null) return null; return new ByteString(source.pos, source.len, source.base); } /** * Creates a ByteString substring. * * @param start the first character of the substring * @param end the character after the last character of the substring * @return the ByteString substring */ public ByteString substring(int start, int end) { return new ByteString(pos+start, end-start, base); } /** * Check if this ByteString equals the value of the passed arguments * * @param b byte array that holds the value to check against * @param pos first byte in the byte array * @param len length of the value to check against * @return true if this ByteString matches, false otherwise */ public final boolean equalsIgnoreCase(byte[] b, int pos, int len) { if (this.len == len) { int thisPos = this.pos; for (int i=0; ; ++i, ++thisPos, ++pos) { if (i == len) return true; if (base[thisPos] != b[pos]) { byte c1 = base[thisPos]; byte c2 = b[pos]; if ('a' <= c1) c1 -= ('a'-'A'); // fast toUpper if ('a' <= c2) c2 -= ('a'-'A'); // fast toUpper if (c1 != c2) break; } } } return false; } /** * Check if this ByteString is equal to the one passed in the argument. * * @param c ByteString to check against * @return true if this ByteString is equal * to the <code>c</code> ByteString, false otherwise. */ public final boolean equalsIgnoreCase(ByteString c) { return equalsIgnoreCase(c.base, c.pos, c.len); } /** * Check if this ByteString equals the byte array <code>b</code>, * for the length of the byte array, starting at <code>at</code> * within this ByteString. * <P> * This extends, some how, startsWidth and endsWidth, avoiding substring. * * @param b byte array that holds the value to check against * @param at first byte in this ByteString * @return true if this ByteString matches, false otherwise */ public final boolean equalsAtIgnoreCase(byte[] b, int at) { if ((at + b.length) > len) return false; int len = this.len; // save! this.pos += at; this.len = b.length; boolean isEqual = equalsIgnoreCase(b, 0, this.len); this.pos -= at; this.len = len; return isEqual; } /** * Return a String representation of this ByteString * * @return a String representation of this ByteString */ public final String toString() { return new String(base, pos, len); } /** * Find the first byte <code>b</code> in this ByteString. * * @param b byte to find * @param start where to start from * @return the offset of the byte, if found; -1 if not found */ public final int indexOf(byte b, int start) { for (int i=start; i < len; ++i) if (base[i+pos] == b) return i; return -1; } /** * Find the last byte <code>b</code> in this ByteString. * * @param b byte to find * @return the offset of the byte, if found; -1 if not found */ public final int lastIndexOf(byte b) { int i; for (i=len+pos-1; (i >= pos) && (base[i] != b); --i); return i-pos; } /** * Find the first byte array <code>b</code> in this ByteString. * * @param b byte array to find * @param start where to start from * @return the offset of the byte array, if found; -1 if not found */ public final int indexOf(byte[] b, int start) { while (true) { start = indexOf(b[0], start); if (start == -1) return -1; for (int i=start+1, k=1; ; ++i, ++k) { if (k == b.length) return start; if ((i == len) || (base[pos+i] != b[k])) break; } ++start; } } /** * Convert the literal representation of an int to its int value * * @param b byte array that holds the literal representation * @param start where it starts in the byte array * @param end where it ends * @return the integer value, or -1 if wrong representation. */ public static int convertToInt(byte[] b, int start, int end) { if (end > start) { int res = 0; while (true) { byte ch = b[start]; if ((ch > (byte)'9') || (ch < (byte)'0')) return -1; res += (ch & 0xF); if (++start == end) return res; res *= 10; } } return 0; } /** * Convert the literal representation of an int to its int value * * @param start where the int represenation starts in this ByteString * @return the integer value, or -1 if wrong representation. */ public int convertToInt(int start) { return convertToInt(base, start+pos, pos+len); } }