private static LLSD ParseNotationElement(string notationData, out int endPos) { if (notationData.Length == 0) { endPos = 0; return(null); } // Identify what type of object this is switch (notationData[0]) { case '!': endPos = 1; return(new LLSD()); case '1': endPos = 1; return(LLSD.FromBoolean(true)); case '0': endPos = 1; return(LLSD.FromBoolean(false)); case 'i': { if (notationData.Length < 2) { endPos = notationData.Length; return(LLSD.FromInteger(0)); } int value; endPos = FindEnd(notationData, 1); if (Helpers.TryParse(notationData.Substring(1, endPos - 1), out value)) { return(LLSD.FromInteger(value)); } else { return(LLSD.FromInteger(0)); } } case 'r': { if (notationData.Length < 2) { endPos = notationData.Length; return(LLSD.FromReal(0d)); } double value; endPos = FindEnd(notationData, 1); if (Helpers.TryParse(notationData.Substring(1, endPos - 1), out value)) { return(LLSD.FromReal(value)); } else { return(LLSD.FromReal(0d)); } } case 'u': { if (notationData.Length < 17) { endPos = notationData.Length; return(LLSD.FromUUID(LLUUID.Zero)); } LLUUID value; endPos = FindEnd(notationData, 1); if (Helpers.TryParse(notationData.Substring(1, endPos - 1), out value)) { return(LLSD.FromUUID(value)); } else { return(LLSD.FromUUID(LLUUID.Zero)); } } case 'b': throw new NotImplementedException("Notation binary type is unimplemented"); case 's': case '"': case '\'': if (notationData.Length < 2) { endPos = notationData.Length; return(LLSD.FromString(String.Empty)); } endPos = FindEnd(notationData, 1); return(LLSD.FromString(notationData.Substring(1, endPos - 1).Trim(new char[] { '"', '\'' }))); case 'l': throw new NotImplementedException("Notation URI type is unimplemented"); case 'd': throw new NotImplementedException("Notation date type is unimplemented"); case '[': { if (notationData.IndexOf(']') == -1) { throw new LLSDException("Invalid notation array"); } int pos = 0; LLSDArray array = new LLSDArray(); while (notationData[pos] != ']') { ++pos; // Advance past comma if need be if (notationData[pos] == ',') { ++pos; } // Allow a single whitespace character if (pos < notationData.Length && notationData[pos] == ' ') { ++pos; } int end; array.Add(ParseNotationElement(notationData.Substring(pos), out end)); pos += end; } endPos = pos + 1; return(array); } case '{': { if (notationData.IndexOf('}') == -1) { throw new LLSDException("Invalid notation map"); } int pos = 0; LLSDMap hashtable = new LLSDMap(); while (notationData[pos] != '}') { ++pos; // Advance past comma if need be if (notationData[pos] == ',') { ++pos; } // Allow a single whitespace character if (pos < notationData.Length && notationData[pos] == ' ') { ++pos; } if (notationData[pos] != '\'') { throw new LLSDException("Expected a map key"); } int endquote = notationData.IndexOf('\'', pos + 1); if (endquote == -1 || (endquote + 1) >= notationData.Length || notationData[endquote + 1] != ':') { throw new LLSDException("Invalid map format"); } string key = notationData.Substring(pos, endquote - pos); key = key.Trim(new char[] { '"', '\'' }); //key.Replace("'", String.Empty); pos += (endquote - pos) + 2; int end; hashtable[key] = ParseNotationElement(notationData.Substring(pos), out end); pos += end; } endPos = pos + 1; return(hashtable); } default: throw new LLSDException("Unknown notation value type"); } }
/// <summary> /// /// </summary> /// <param name="reader"></param> /// <returns></returns> private static LLSD DeserializeNotationElement(StringReader reader) { int character = ReadAndSkipWhitespace(reader); if (character < 0) { return(new LLSD()); // server returned an empty file, so we're going to pass along a null LLSD object } LLSD llsd; int matching; switch ((char)character) { case undefNotationValue: llsd = new LLSD(); break; case trueNotationValueOne: llsd = LLSD.FromBoolean(true); break; case trueNotationValueTwo: matching = BufferCharactersEqual(reader, trueNotationValueTwoFull, 1); if (matching > 1 && matching < trueNotationValueTwoFull.Length) { throw new LLSDException("Notation LLSD parsing: True value parsing error:"); } llsd = LLSD.FromBoolean(true); break; case trueNotationValueThree: matching = BufferCharactersEqual(reader, trueNotationValueThreeFull, 1); if (matching > 1 && matching < trueNotationValueThreeFull.Length) { throw new LLSDException("Notation LLSD parsing: True value parsing error:"); } llsd = LLSD.FromBoolean(true); break; case falseNotationValueOne: llsd = LLSD.FromBoolean(false); break; case falseNotationValueTwo: matching = BufferCharactersEqual(reader, falseNotationValueTwoFull, 1); if (matching > 1 && matching < falseNotationValueTwoFull.Length) { throw new LLSDException("Notation LLSD parsing: True value parsing error:"); } llsd = LLSD.FromBoolean(false); break; case falseNotationValueThree: matching = BufferCharactersEqual(reader, falseNotationValueThreeFull, 1); if (matching > 1 && matching < falseNotationValueThreeFull.Length) { throw new LLSDException("Notation LLSD parsing: True value parsing error:"); } llsd = LLSD.FromBoolean(false); break; case integerNotationMarker: llsd = DeserializeNotationInteger(reader); break; case realNotationMarker: llsd = DeserializeNotationReal(reader); break; case uuidNotationMarker: char[] uuidBuf = new char[36]; if (reader.Read(uuidBuf, 0, 36) < 36) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in UUID."); } LLUUID lluuid; if (!LLUUID.TryParse(new String(uuidBuf), out lluuid)) { throw new LLSDException("Notation LLSD parsing: Invalid UUID discovered."); } llsd = LLSD.FromUUID(lluuid); break; case binaryNotationMarker: byte[] bytes = new byte[0]; int bChar = reader.Peek(); if (bChar < 0) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in binary."); } if ((char)bChar == sizeBeginNotationMarker) { throw new LLSDException("Notation LLSD parsing: Raw binary encoding not supported."); } else if (Char.IsDigit((char)bChar)) { char[] charsBaseEncoding = new char[2]; if (reader.Read(charsBaseEncoding, 0, 2) < 2) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in binary."); } int baseEncoding; if (!Int32.TryParse(new String(charsBaseEncoding), out baseEncoding)) { throw new LLSDException("Notation LLSD parsing: Invalid binary encoding base."); } if (baseEncoding == 64) { if (reader.Read() < 0) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in binary."); } string bytes64 = GetStringDelimitedBy(reader, doubleQuotesNotationMarker); bytes = Convert.FromBase64String(bytes64); } else { throw new LLSDException("Notation LLSD parsing: Encoding base" + baseEncoding + " + not supported."); } } llsd = LLSD.FromBinary(bytes); break; case stringNotationMarker: int numChars = GetLengthInBrackets(reader); if (reader.Read() < 0) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in string."); } char[] chars = new char[numChars]; if (reader.Read(chars, 0, numChars) < numChars) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in string."); } if (reader.Read() < 0) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in string."); } llsd = LLSD.FromString(new String(chars)); break; case singleQuotesNotationMarker: string sOne = GetStringDelimitedBy(reader, singleQuotesNotationMarker); llsd = LLSD.FromString(sOne); break; case doubleQuotesNotationMarker: string sTwo = GetStringDelimitedBy(reader, doubleQuotesNotationMarker); llsd = LLSD.FromString(sTwo); break; case uriNotationMarker: if (reader.Read() < 0) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in string."); } string sUri = GetStringDelimitedBy(reader, doubleQuotesNotationMarker); Uri uri; try { uri = new Uri(sUri, UriKind.RelativeOrAbsolute); } catch { throw new LLSDException("Notation LLSD parsing: Invalid Uri format detected."); } llsd = LLSD.FromUri(uri); break; case dateNotationMarker: if (reader.Read() < 0) { throw new LLSDException("Notation LLSD parsing: Unexpected end of stream in date."); } string date = GetStringDelimitedBy(reader, doubleQuotesNotationMarker); DateTime dt; if (!Helpers.TryParse(date, out dt)) { throw new LLSDException("Notation LLSD parsing: Invalid date discovered."); } llsd = LLSD.FromDate(dt); break; case arrayBeginNotationMarker: llsd = DeserializeNotationArray(reader); break; case mapBeginNotationMarker: llsd = DeserializeNotationMap(reader); break; default: throw new LLSDException("Notation LLSD parsing: Unknown type marker '" + (char)character + "'."); } return(llsd); }
private static LLSD ParseXmlElement(XmlTextReader reader) { SkipWhitespace(reader); if (reader.NodeType != XmlNodeType.Element) { throw new LLSDException("Expected an element"); } string type = reader.LocalName; LLSD ret; switch (type) { case "undef": if (reader.IsEmptyElement) { reader.Read(); return(new LLSD()); } reader.Read(); SkipWhitespace(reader); ret = new LLSD(); break; case "boolean": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromBoolean(false)); } if (reader.Read()) { string s = reader.ReadString().Trim(); if (!String.IsNullOrEmpty(s) && (s == "true" || s == "1")) { ret = LLSD.FromBoolean(true); break; } } ret = LLSD.FromBoolean(false); break; case "integer": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromInteger(0)); } if (reader.Read()) { int value = 0; Helpers.TryParse(reader.ReadString().Trim(), out value); ret = LLSD.FromInteger(value); break; } ret = LLSD.FromInteger(0); break; case "real": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromReal(0d)); } if (reader.Read()) { double value = 0d; string str = reader.ReadString().Trim().ToLower(); if (str == "nan") { value = Double.NaN; } else { Helpers.TryParse(str, out value); } ret = LLSD.FromReal(value); break; } ret = LLSD.FromReal(0d); break; case "uuid": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromUUID(LLUUID.Zero)); } if (reader.Read()) { LLUUID value = LLUUID.Zero; LLUUID.TryParse(reader.ReadString().Trim(), out value); ret = LLSD.FromUUID(value); break; } ret = LLSD.FromUUID(LLUUID.Zero); break; case "date": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromDate(Helpers.Epoch)); } if (reader.Read()) { DateTime value = Helpers.Epoch; Helpers.TryParse(reader.ReadString().Trim(), out value); ret = LLSD.FromDate(value); break; } ret = LLSD.FromDate(Helpers.Epoch); break; case "string": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromString(String.Empty)); } if (reader.Read()) { ret = LLSD.FromString(reader.ReadString()); break; } ret = LLSD.FromString(String.Empty); break; case "binary": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromBinary(new byte[0])); } if (reader.GetAttribute("encoding") != null && reader.GetAttribute("encoding") != "base64") { throw new LLSDException("Unsupported binary encoding: " + reader.GetAttribute("encoding")); } if (reader.Read()) { try { ret = LLSD.FromBinary(Convert.FromBase64String(reader.ReadString().Trim())); break; } catch (FormatException ex) { throw new LLSDException("Binary decoding exception: " + ex.Message); } } ret = LLSD.FromBinary(new byte[0]); break; case "uri": if (reader.IsEmptyElement) { reader.Read(); return(LLSD.FromUri(new Uri(String.Empty, UriKind.RelativeOrAbsolute))); } if (reader.Read()) { ret = LLSD.FromUri(new Uri(reader.ReadString(), UriKind.RelativeOrAbsolute)); break; } ret = LLSD.FromUri(new Uri(String.Empty, UriKind.RelativeOrAbsolute)); break; case "map": return(ParseXmlMap(reader)); case "array": return(ParseXmlArray(reader)); default: reader.Read(); ret = null; break; } if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != type) { throw new LLSDException("Expected </" + type + ">"); } else { reader.Read(); return(ret); } }
private static LLSD ParseBinaryElement(MemoryStream stream) { SkipWhiteSpace(stream); LLSD llsd; int marker = stream.ReadByte(); if (marker < 0) { throw new LLSDException("Binary LLSD parsing:Unexpected end of stream."); } switch ((byte)marker) { case undefBinaryValue: llsd = new LLSD(); break; case trueBinaryValue: llsd = LLSD.FromBoolean(true); break; case falseBinaryValue: llsd = LLSD.FromBoolean(false); break; case integerBinaryMarker: int integer = NetworkToHostInt(ConsumeBytes(stream, int32Length)); llsd = LLSD.FromInteger(integer); break; case realBinaryMarker: double dbl = NetworkToHostDouble(ConsumeBytes(stream, doubleLength)); llsd = LLSD.FromReal(dbl); break; case uuidBinaryMarker: llsd = LLSD.FromUUID(new LLUUID(ConsumeBytes(stream, 16), 0)); break; case binaryBinaryMarker: int binaryLength = NetworkToHostInt(ConsumeBytes(stream, int32Length)); llsd = LLSD.FromBinary(ConsumeBytes(stream, binaryLength)); break; case stringBinaryMarker: int stringLength = NetworkToHostInt(ConsumeBytes(stream, int32Length)); string ss = Encoding.UTF8.GetString(ConsumeBytes(stream, stringLength)); llsd = LLSD.FromString(ss); break; case uriBinaryMarker: int uriLength = NetworkToHostInt(ConsumeBytes(stream, int32Length)); string sUri = Encoding.UTF8.GetString(ConsumeBytes(stream, uriLength)); Uri uri; try { uri = new Uri(sUri, UriKind.RelativeOrAbsolute); } catch { throw new LLSDException("Binary LLSD parsing: Invalid Uri format detected."); } llsd = LLSD.FromUri(uri); break; case dateBinaryMarker: double timestamp = NetworkToHostDouble(ConsumeBytes(stream, doubleLength)); DateTime dateTime = DateTime.SpecifyKind(Helpers.Epoch, DateTimeKind.Utc); dateTime = dateTime.AddSeconds(timestamp); llsd = LLSD.FromDate(dateTime.ToLocalTime()); break; case arrayBeginBinaryMarker: llsd = ParseBinaryArray(stream); break; case mapBeginBinaryMarker: llsd = ParseBinaryMap(stream); break; default: throw new LLSDException("Binary LLSD parsing: Unknown type marker."); } return(llsd); }