/// <summary> /// Extract an integer, starting at the current position. Updates the /// internal index to beyond the number. Returns -1 if a number was /// not found. /// </summary> /// <returns>a number</returns> public int ReadNumber() { // Skip leading spaces SkipSpaces(); int start = index; while (index < size && char.IsDigit((char)buffer[index])) { index++; } if (index > start) { try { return(ASCIIUtility.ParseInt(buffer, start, index)); } catch (FormatException) { } } return(-1); }
/// <summary> /// Generic parsing routine that can parse out a Quoted-String, /// Literal or Atom and return the parsed token as a String /// or a ByteArray. Errors or NIL data will return null. /// </summary> private object parseString(bool parseAtoms, bool returnString) { byte b; // Skip leading spaces SkipSpaces(); b = buffer[index]; if (b == '"') { // QuotedString index++; // skip the quote int start = index; int copyto = index; while (index < size && (b = buffer[index]) != '"') { if (b == '\\') // skip escaped byte { index++; } if (index != copyto) { // only copy if we need to // Beware: this is a destructive copy. I'm // pretty sure this is OK, but ... ;> buffer[copyto] = buffer[index]; } copyto++; index++; } if (index >= size) { // didn't find terminating quote, something is seriously wrong //throw new ArrayIndexOutOfBoundsException( // "index = " + index + ", size = " + size); return(null); } else { index++; // skip past the terminating quote } if (returnString) { return(toString(buffer, start, copyto)); } else { return(new ByteArray(buffer, start, copyto - start)); } } else if (b == '{') { // Literal int start = ++index; // note the start position while (buffer[index] != '}') { index++; } int count = 0; try { count = ASCIIUtility.ParseInt(buffer, start, index); } catch (FormatException nex) { // throw new ParsingException(); return(null); } start = index + 3; // skip "}\r\n" index = start + count; // position index to beyond the literal if (returnString) // return as String { return(toString(buffer, start, start + count)); } else { return(new ByteArray(buffer, start, count)); } } else if (parseAtoms) { // parse as ASTRING-CHARs int start = index; // track this, so that we can use to // creating ByteArrayInputStream below. String s = readDelimString(ASTRING_CHAR_DELIM); if (returnString) { return(s); } else // *very* unlikely { return(new ByteArray(buffer, start, index)); } } else if (b == 'N' || b == 'n') { // the only valid value is 'NIL' index += 3; // skip past NIL return(null); } return(null); // Error }
/// <summary> /// Read a Response from the Stream. /// </summary> /// <param name="ba">the ByteArray in which to store the response, or null</param> /// <returns>ByteArray that contains the Response</returns> /// <exception cref="IOException">for I/O errors</exception> public ByteArray ReadResponse(ByteArray ba) { if (ba.IsNull()) { ba = new ByteArray(128); } byte[] buffer = ba.Bytes; int idx = 0; for (;;) {// read until CRLF with no preceeding literal // XXX - b needs to be an int, to handle bytes with value 0xff int b = 0; bool gotCRLF = false; // Read a CRLF terminated line from the InputStream while (!gotCRLF && (b = bin.ReadByte()) != -1) { if (b == '\n') { if (idx > 0 && buffer[idx - 1] == '\r') { gotCRLF = true; } } if (idx >= buffer.Length) { int incr = buffer.Length; if (incr > maxIncrement) { incr = maxIncrement; } ba.Increase(incr); buffer = ba.Bytes; } buffer[idx++] = (byte)b; } if (b == -1) { throw new IOException("Connection dropped by server?"); } // Now lets check for literals : {<digits>}CRLF // Note: index needs to >= 5 for the above sequence to occur if (idx < 5 || buffer[idx - 3] != '}') { break; } int i; // look for left curly for (i = idx - 4; i >= 0; i--) { if (buffer[i] == '{') { break; } } if (i < 0) // Nope, not a literal ? { break; } int count = 0; // OK, handle the literal .. try { count = ASCIIUtility.ParseInt(buffer, i + 1, idx - 3); } catch (FormatException) { break; } // Now read 'count' bytes. (Note: count could be 0) if (count > 0) { int avail = buffer.Length - idx; // available space in buffer if (count + incrementSlop > avail) { // need count-avail more bytes ba.Increase(minIncrement > count + incrementSlop - avail ? minIncrement : count + incrementSlop - avail); buffer = ba.Bytes; } /* * read() might not return all the bytes in one shot, * so call repeatedly till we are done */ int actual; while (count > 0) { actual = bin.Read(buffer, idx, count); if (actual == -1) { throw new IOException("Connection dropped by server?"); } count -= actual; idx += actual; } } // back to top of loop to read until CRLF } ba.Length = idx; return(ba); }