diff --git a/plist-cil/ASCIIPropertyListParser.cs b/plist-cil/ASCIIPropertyListParser.cs new file mode 100644 index 0000000..f7c537d --- /dev/null +++ b/plist-cil/ASCIIPropertyListParser.cs @@ -0,0 +1,650 @@ +// plist-cil - An open source library to parse and generate property lists for .NET +// Copyright (C) 2015 Natalia Portillo +// +// This code is based on: +// plist - An open source library to parse and generate property lists +// Copyright (C) 2014 Daniel Dreibrodt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +using System; +using System.IO; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Globalization; +using System.Text; +using System.Runtime.CompilerServices; + +namespace Claunia.PropertyList +{ + /// + ///

+ /// Parser for ASCII property lists. Supports Apple OS X/iOS and GnuStep/NeXTSTEP format. + /// This parser is based on the recursive descent paradigm, but the underlying grammar + /// is not explicitely defined. + ///

+ ///

+ /// Resources on ASCII property list format: + ///

+ /// + ///
+ /// @author Daniel Dreibrodt + public class ASCIIPropertyListParser + { + /// + /// Parses an ASCII property list file. + /// + /// The ASCII property list file.. + /// The root object of the property list. This is usually a NSDictionary but can also be a NSArray. + /// When an error occurs during parsing. + /// When an error occured while reading from the input stream. + public static NSObject Parse(FileInfo f) { + return Parse(f.OpenRead()); + } + + /// + /// Parses an ASCII property list from an input stream. + /// + /// The input stream that points to the property list's data. + /// The root object of the property list. This is usually a NSDictionary but can also be a NSArray. + /// When an error occurs during parsing. + /// + public static NSObject Parse(Stream fs) { + byte[] buf = PropertyListParser.ReadAll(fs); + fs.Close(); + return Parse(buf); + } + + /// + /// Parses an ASCII property list from a byte array. + /// + /// The ASCII property list data. + /// The root object of the property list. This is usually a NSDictionary but can also be a NSArray. + /// When an error occurs during parsing. + public static NSObject Parse(byte[] bytes) { + ASCIIPropertyListParser parser = new ASCIIPropertyListParser(bytes); + return parser.Parse(); + } + + public const char WHITESPACE_SPACE = ' '; + public const char WHITESPACE_TAB = '\t'; + public const char WHITESPACE_NEWLINE = '\n'; + public const char WHITESPACE_CARRIAGE_RETURN = '\r'; + + public const char ARRAY_BEGIN_TOKEN = '('; + public const char ARRAY_END_TOKEN = ')'; + public const char ARRAY_ITEM_DELIMITER_TOKEN = ','; + + public const char DICTIONARY_BEGIN_TOKEN = '{'; + public const char DICTIONARY_END_TOKEN = '}'; + public const char DICTIONARY_ASSIGN_TOKEN = '='; + public const char DICTIONARY_ITEM_DELIMITER_TOKEN = ';'; + + public const char QUOTEDSTRING_BEGIN_TOKEN = '"'; + public const char QUOTEDSTRING_END_TOKEN = '"'; + public const char QUOTEDSTRING_ESCAPE_TOKEN = '\\'; + + public const char DATA_BEGIN_TOKEN = '<'; + public const char DATA_END_TOKEN = '>'; + + public const char DATA_GSOBJECT_BEGIN_TOKEN = '*'; + public const char DATA_GSDATE_BEGIN_TOKEN = 'D'; + public const char DATA_GSBOOL_BEGIN_TOKEN = 'B'; + public const char DATA_GSBOOL_TRUE_TOKEN = 'Y'; + public const char DATA_GSBOOL_FALSE_TOKEN = 'N'; + public const char DATA_GSINT_BEGIN_TOKEN = 'I'; + public const char DATA_GSREAL_BEGIN_TOKEN = 'R'; + + public const char DATE_DATE_FIELD_DELIMITER = '-'; + public const char DATE_TIME_FIELD_DELIMITER = ':'; + public const char DATE_GS_DATE_TIME_DELIMITER = ' '; + public const char DATE_APPLE_DATE_TIME_DELIMITER = 'T'; + public const char DATE_APPLE_END_TOKEN = 'Z'; + + public const char COMMENT_BEGIN_TOKEN = '/'; + public const char MULTILINE_COMMENT_SECOND_TOKEN = '*'; + public const char SINGLELINE_COMMENT_SECOND_TOKEN = '/'; + public const char MULTILINE_COMMENT_END_TOKEN = '/'; + + /** + * Property list source data + */ + private byte[] data; + /** + * Current parsing index + */ + private int index; + + /** + * Only allow subclasses to change instantiation. + */ + protected ASCIIPropertyListParser() { + + } + + /// + /// Creates a new parser for the given property list content. + /// + /// The content of the property list that is to be parsed. + private ASCIIPropertyListParser(byte[] propertyListContent) { + data = propertyListContent; + } + + /// + /// Checks whether the given sequence of symbols can be accepted. + /// + /// Whether the given tokens occur at the current parsing position. + /// The sequence of tokens to look for. + private bool AcceptSequence(params char[] sequence) { + for (int i = 0; i < sequence.Length; i++) { + if (data[index + i] != sequence[i]) + return false; + } + return true; + } + + /// + /// Checks whether the given symbols can be accepted, that is, if one + /// of the given symbols is found at the current parsing position. + /// + /// The symbols to check. + /// Whether one of the symbols can be accepted or not. + private bool Accept(params char[] acceptableSymbols) { + bool symbolPresent = false; + foreach (char c in acceptableSymbols) { + if (data[index] == c) + symbolPresent = true; + } + return symbolPresent; + } + + /// + /// Checks whether the given symbol can be accepted, that is, if + /// the given symbols is found at the current parsing position. + /// + /// The symbol to check. + /// Whether the symbol can be accepted or not. + private bool Accept(char acceptableSymbol) { + return data[index] == acceptableSymbol; + } + + /// + /// Expects the input to have one of the given symbols at the current parsing position. + /// + /// The expected symbols. + /// If none of the expected symbols could be found. + private void Expect(params char[] expectedSymbols) { + if (!Accept(expectedSymbols)) { + String excString = "Expected '" + expectedSymbols[0] + "'"; + for (int i = 1; i < expectedSymbols.Length; i++) { + excString += " or '" + expectedSymbols[i] + "'"; + } + excString += " but found '" + (char) data[index] + "'"; + throw new FormatException(String.Format("{0} at {1}", excString, index)); + } + } + + /// + /// Expects the input to have the given symbol at the current parsing position. + /// + /// The expected symbol. + /// If the expected symbol could be found. + private void Expect(char expectedSymbol) { + if (!Accept(expectedSymbol)) + throw new FormatException(String.Format("Expected '{0}' but found '{1}' at {2}", expectedSymbol, data[index], index)); + } + + /// + /// Reads an expected symbol. + /// + /// The symbol to read. + /// If the expected symbol could not be read. + private void Read(char symbol) { + Expect(symbol); + index++; + } + + /** + * Skips the current symbol. + */ + private void Skip() { + index++; + } + + /// + /// Skips several symbols + /// + /// The amount of symbols to skip. + private void Skip(int numSymbols) { + index += numSymbols; + } + + /** + * Skips all whitespaces and comments from the current parsing position onward. + */ + private void SkipWhitespacesAndComments() { + bool commentSkipped; + do { + commentSkipped = false; + + //Skip whitespaces + while (Accept(WHITESPACE_CARRIAGE_RETURN, WHITESPACE_NEWLINE, WHITESPACE_SPACE, WHITESPACE_TAB)) { + Skip(); + } + + //Skip single line comments "//..." + if (AcceptSequence(COMMENT_BEGIN_TOKEN, SINGLELINE_COMMENT_SECOND_TOKEN)) { + Skip(2); + ReadInputUntil(WHITESPACE_CARRIAGE_RETURN, WHITESPACE_NEWLINE); + commentSkipped = true; + } + //Skip multi line comments "/* ... */" + else if (AcceptSequence(COMMENT_BEGIN_TOKEN, MULTILINE_COMMENT_SECOND_TOKEN)) { + Skip(2); + while (true) { + if (AcceptSequence(MULTILINE_COMMENT_SECOND_TOKEN, MULTILINE_COMMENT_END_TOKEN)) { + Skip(2); + break; + } + Skip(); + } + commentSkipped = true; + } + } + while (commentSkipped); //if a comment was skipped more whitespace or another comment can follow, so skip again + } + + /// + /// Reads input until one of the given symbols is found. + /// + /// The input until one the given symbols. + /// The symbols that can occur after the string to read. + private string ReadInputUntil(params char[] symbols) { + string s = ""; + while (!Accept(symbols)) { + s += (char) data[index]; + Skip(); + } + return s; + } + + /// + /// Reads input until the given symbol is found. + /// + /// The input until the given symbol. + /// The symbol that can occur after the string to read. + private string ReadInputUntil(char symbol) { + String s = ""; + while (!Accept(symbol)) { + s += (char) data[index]; + Skip(); + } + return s; + } + + /// + /// Parses the property list from the beginning and returns the root object + /// of the property list. + /// + /// The root object of the property list. This can either be a NSDictionary or a NSArray. + /// When an error occured during parsing + public NSObject Parse() { + index = 0; + SkipWhitespacesAndComments(); + Expect(DICTIONARY_BEGIN_TOKEN, ARRAY_BEGIN_TOKEN, COMMENT_BEGIN_TOKEN); + try { + return ParseObject(); + } catch (IndexOutOfRangeException ex) { + throw new FormatException(String.Format("Reached end of input unexpectedly at {0}.", index)); + } + } + + /// + /// Parses the NSObject found at the current position in the property list + /// data stream. + /// + /// The parsed NSObject. + /// + private NSObject ParseObject() { + switch (data[index]) { + case (byte)ARRAY_BEGIN_TOKEN: { + return ParseArray(); + } + case (byte)DICTIONARY_BEGIN_TOKEN: { + return ParseDictionary(); + } + case (byte)DATA_BEGIN_TOKEN: { + return ParseData(); + } + case (byte)QUOTEDSTRING_BEGIN_TOKEN: { + string quotedString = ParseQuotedString(); + //apple dates are quoted strings of length 20 and after the 4 year digits a dash is found + if (quotedString.Length == 20 && quotedString[4] == DATE_DATE_FIELD_DELIMITER) { + try { + return new NSDate(quotedString); + } catch (Exception ex) { + //not a date? --> return string + return new NSString(quotedString); + } + } else { + return new NSString(quotedString); + } + } + default: { + //0-9 + if (data[index] > 0x2F && data[index] < 0x3A) { + //could be a date or just a string + return ParseDateString(); + } else { + //non-numerical -> string or boolean + string parsedString = ParseString(); + return new NSString(parsedString); + } + } + } + } + + /// + /// Parses an array from the current parsing position. + /// The prerequisite for calling this method is, that an array begin token has been read. + /// + /// The array found at the parsing position. + private NSArray ParseArray() { + //Skip begin token + Skip(); + SkipWhitespacesAndComments(); + List objects = new List(); + while (!Accept(ARRAY_END_TOKEN)) { + objects.Add(ParseObject()); + SkipWhitespacesAndComments(); + if (Accept(ARRAY_ITEM_DELIMITER_TOKEN)) { + Skip(); + } else { + break; //must have reached end of array + } + SkipWhitespacesAndComments(); + } + //parse end token + Read(ARRAY_END_TOKEN); + return new NSArray(objects.ToArray()); + } + + /// + /// Parses a dictionary from the current parsing position. + /// The prerequisite for calling this method is, that a dictionary begin token has been read. + /// + /// The dictionary found at the parsing position. + private NSDictionary ParseDictionary() { + //Skip begin token + Skip(); + SkipWhitespacesAndComments(); + NSDictionary dict = new NSDictionary(); + while (!Accept(DICTIONARY_END_TOKEN)) { + //Parse key + string keyString; + if (Accept(QUOTEDSTRING_BEGIN_TOKEN)) { + keyString = ParseQuotedString(); + } else { + keyString = ParseString(); + } + SkipWhitespacesAndComments(); + + //Parse assign token + Read(DICTIONARY_ASSIGN_TOKEN); + SkipWhitespacesAndComments(); + + NSObject nso = ParseObject(); + dict.Add(keyString, nso); + SkipWhitespacesAndComments(); + Read(DICTIONARY_ITEM_DELIMITER_TOKEN); + SkipWhitespacesAndComments(); + } + //skip end token + Skip(); + return dict; + } + + /// + /// Parses a data object from the current parsing position. + /// This can either be a NSData object or a GnuStep NSNumber or NSDate. + /// The prerequisite for calling this method is, that a data begin token has been read. + /// + /// The data object found at the parsing position. + private NSObject ParseData() { + NSObject obj = null; + //Skip begin token + Skip(); + if (Accept(DATA_GSOBJECT_BEGIN_TOKEN)) { + Skip(); + Expect(DATA_GSBOOL_BEGIN_TOKEN, DATA_GSDATE_BEGIN_TOKEN, DATA_GSINT_BEGIN_TOKEN, DATA_GSREAL_BEGIN_TOKEN); + if (Accept(DATA_GSBOOL_BEGIN_TOKEN)) { + //Boolean + Skip(); + Expect(DATA_GSBOOL_TRUE_TOKEN, DATA_GSBOOL_FALSE_TOKEN); + if (Accept(DATA_GSBOOL_TRUE_TOKEN)) { + obj = new NSNumber(true); + } else { + obj = new NSNumber(false); + } + //Skip the parsed boolean token + Skip(); + } else if (Accept(DATA_GSDATE_BEGIN_TOKEN)) { + //Date + Skip(); + string dateString = ReadInputUntil(DATA_END_TOKEN); + obj = new NSDate(dateString); + } else if (Accept(DATA_GSINT_BEGIN_TOKEN, DATA_GSREAL_BEGIN_TOKEN)) { + //Number + Skip(); + string numberString = ReadInputUntil(DATA_END_TOKEN); + obj = new NSNumber(numberString); + } + //parse data end token + Read(DATA_END_TOKEN); + } else { + string dataString = ReadInputUntil(DATA_END_TOKEN); + dataString = Regex.Replace(dataString, "\\s+", ""); + + int numBytes = dataString.Length / 2; + byte[] bytes = new byte[numBytes]; + for (int i = 0; i < bytes.Length; i++) { + string byteString = dataString.Substring(i * 2, i * 2 + 2); + int byteValue = Convert.ToInt32(byteString, 16); + bytes[i] = (byte) byteValue; + } + obj = new NSData(bytes); + + //skip end token + Skip(); + } + + return obj; + } + + /// + /// Attempts to parse a plain string as a date if possible. + /// + /// A NSDate if the string represents such an object. Otherwise a NSString is returned. + private NSObject ParseDateString() { + string numericalString = ParseString(); + if (numericalString.Length > 4 && numericalString[4] == DATE_DATE_FIELD_DELIMITER) { + try { + return new NSDate(numericalString); + } catch(Exception ex) { + //An exception occurs if the string is not a date but just a string + } + } + return new NSString(numericalString); + } + + /// + /// Parses a plain string from the current parsing position. + /// The string is made up of all characters to the next whitespace, delimiter token or assignment token. + /// + /// The string found at the current parsing position. + private string ParseString() { + return ReadInputUntil(WHITESPACE_SPACE, WHITESPACE_TAB, WHITESPACE_NEWLINE, WHITESPACE_CARRIAGE_RETURN, + ARRAY_ITEM_DELIMITER_TOKEN, DICTIONARY_ITEM_DELIMITER_TOKEN, DICTIONARY_ASSIGN_TOKEN, ARRAY_END_TOKEN); + } + + /// + /// Parses a quoted string from the current parsing position. + /// The prerequisite for calling this method is, that a quoted string begin token has been read. + /// + /// The quoted string found at the parsing method with all special characters unescaped. + /// If an error occured during parsing. + private string ParseQuotedString() { + //Skip begin token + Skip(); + string quotedString = ""; + bool unescapedBackslash = true; + //Read from opening quotation marks to closing quotation marks and skip escaped quotation marks + while (data[index] != QUOTEDSTRING_END_TOKEN || (data[index - 1] == QUOTEDSTRING_ESCAPE_TOKEN && unescapedBackslash)) { + quotedString += (char) data[index]; + if (Accept(QUOTEDSTRING_ESCAPE_TOKEN)) { + unescapedBackslash = !(data[index - 1] == QUOTEDSTRING_ESCAPE_TOKEN && unescapedBackslash); + } + Skip(); + } + string unescapedString; + try { + unescapedString = ParseQuotedString(quotedString); + } catch (Exception ex) { + throw new FormatException(String.Format("The quoted string could not be parsed at {0}.", index)); + } + //skip end token + Skip(); + return unescapedString; + } + + /** + * Used to encode the parsed strings + */ + private static Encoding asciiEncoder; + + /// + /// Parses a string according to the format specified for ASCII property lists. + /// Such strings can contain escape sequences which are unescaped in this method. + /// + /// The unescaped string in UTF-8 or ASCII format, depending on the contained characters. + /// The escaped string according to the ASCII property list format, without leading and trailing quotation marks. + /// If the en-/decoder for the UTF-8 or ASCII encoding could not be loaded + /// If the string is encoded neither in ASCII nor in UTF-8 + [MethodImpl(MethodImplOptions.Synchronized)] + public static string ParseQuotedString(string s) { + List strBytes = new List(); + CharEnumerator c = s.GetEnumerator(); + + while(c.MoveNext()) { + switch (c.Current) { + case '\\': { //An escaped sequence is following + byte[] bts = Encoding.UTF8.GetBytes(ParseEscapedSequence(c)); + foreach (byte b in bts) + strBytes.Add(b); + break; + } + default: { //a normal ASCII char + strBytes.Add((byte) 0); + strBytes.Add((byte) c.Current); + break; + } + } + } + byte[] bytArr = new byte[strBytes.Count]; + int i = 0; + foreach (byte b in strBytes) { + bytArr[i] = b; + i++; + } + //Build string + string result = Encoding.UTF8.GetString(bytArr); + //emoryStream charBuf = CharBuffer.wrap(result); + + //If the string can be represented in the ASCII codepage + // --> use ASCII encoding + try{ + if (asciiEncoder == null) + asciiEncoder = Encoding.GetEncoding("ascii", EncoderExceptionFallback.ExceptionFallback, DecoderExceptionFallback.ExceptionFallback); + return asciiEncoder.GetString(Encoding.Convert(Encoding.UTF8, asciiEncoder, bytArr)); + } + catch + { + //The string contains characters outside the ASCII codepage + // --> use the UTF-8 encoded string + return result; + } + } + + /// + /// Unescapes an escaped character sequence, e.g. \\u00FC. + /// + /// The unescaped character as a string. + /// The string character iterator pointing to the first character after the backslash + /// If an invalid Unicode or ASCII escape sequence is found. + private static string ParseEscapedSequence(CharEnumerator iterator) { + iterator.MoveNext(); + char c = iterator.Current; + if (c == '\\') { + return Encoding.UTF8.GetString(new byte[]{0, (byte)'\\'}); + } else if (c == '"') { + return Encoding.UTF8.GetString(new byte[]{0, (byte)'\"'}); + } else if (c == 'b') { + return Encoding.UTF8.GetString(new byte[]{0, (byte)'\b'}); + } else if (c == 'n') { + return Encoding.UTF8.GetString(new byte[]{0, (byte)'\n'}); + } else if (c == 'r') { + return Encoding.UTF8.GetString(new byte[]{0, (byte)'\r'}); + } else if (c == 't') { + return Encoding.UTF8.GetString(new byte[]{0, (byte)'\t'}); + } else if (c == 'U' || c == 'u') { + //4 digit hex Unicode value + string byte1 = ""; + iterator.MoveNext(); + byte1 += iterator.Current; + iterator.MoveNext(); + byte1 += iterator.Current; + string byte2 = ""; + iterator.MoveNext(); + byte2 += iterator.Current; + iterator.MoveNext(); + byte2 += iterator.Current; + byte[] stringBytes = {(byte) Convert.ToInt32(byte1, 16), (byte) Convert.ToInt32(byte2, 16)}; + return Encoding.UTF8.GetString(stringBytes); + } else { + //3 digit octal ASCII value + string num = ""; + num += c; + iterator.MoveNext(); + num += iterator.Current; + iterator.MoveNext(); + num += iterator.Current; + int asciiCode = Convert.ToInt32(num, 8); + byte[] stringBytes = {0, (byte) asciiCode}; + return Encoding.UTF8.GetString(stringBytes); + } + } + } +} + diff --git a/plist-cil/ChangeLog b/plist-cil/ChangeLog index e671cb7..caae4e5 100644 --- a/plist-cil/ChangeLog +++ b/plist-cil/ChangeLog @@ -1,3 +1,19 @@ +2015-02-19 Natalia Portillo + + * UID.cs: + * NSSet.cs: + * NSDate.cs: + * NSData.cs: + * NSArray.cs: + * NSNumber.cs: + * NSObject.cs: + * NSString.cs: + * NSDictionary.cs: + * plist-cil.csproj: + * PropertyListParser.cs: + * ASCIIPropertyListParser.cs: + Implement ASCIIPropertyListParser + 2015-02-18 Natalia Portillo * plist-cil.csproj: diff --git a/plist-cil/NSArray.cs b/plist-cil/NSArray.cs index 690edca..50ab7e1 100644 --- a/plist-cil/NSArray.cs +++ b/plist-cil/NSArray.cs @@ -39,7 +39,8 @@ namespace Claunia.PropertyList /// Creates an empty array of the given length. /// /// The number of elements this array will be able to hold. - public NSArray(int length) { + public NSArray(int length) + { array = new NSObject[length]; } @@ -47,7 +48,8 @@ namespace Claunia.PropertyList /// Creates a array from an existing one /// /// The array which should be wrapped by the NSArray - public NSArray(params NSObject[] a) { + public NSArray(params NSObject[] a) + { array = a; } @@ -56,7 +58,8 @@ namespace Claunia.PropertyList /// /// The object at the given index. /// The index of the object. - public NSObject ObjectAtIndex(int i) { + public NSObject ObjectAtIndex(int i) + { return array[i]; } @@ -65,7 +68,8 @@ namespace Claunia.PropertyList /// The array will be resized. /// /// The index of the object - public void Remove(int i) { + public void Remove(int i) + { if ((i >= array.Length) || (i < 0)) throw new IndexOutOfRangeException("invalid index:" + i + ";the array length is " + array.Length); NSObject[] newArray = new NSObject[array.Length - 1]; @@ -80,8 +84,9 @@ namespace Claunia.PropertyList /// /// The index where to store the object. /// The object. - public void SetValue(int key, Object value) { - if(value == null) + public void SetValue(int key, Object value) + { + if (value == null) throw new ArgumentNullException("Cannot add null values to an NSArray!"); array[key] = NSObject.Wrap(value); } @@ -91,7 +96,8 @@ namespace Claunia.PropertyList /// Any changes to the values of this array will also affect the NSArray. /// /// The actual array represented by this NSArray. - public NSObject[] GetArray() { + public NSObject[] GetArray() + { return array; } @@ -99,7 +105,8 @@ namespace Claunia.PropertyList /// Returns the size of the array. /// /// The number of elements that this array can store. - public int Count { + public int Count + { get { return array.Length; @@ -112,10 +119,13 @@ namespace Claunia.PropertyList /// /// true, when the object could be found. false otherwise. /// The object to look for. - public bool ContainsObject(Object obj) { + public bool ContainsObject(Object obj) + { NSObject nso = NSObject.Wrap(obj); - foreach (NSObject elem in array) { - if (elem.Equals(nso)) { + foreach (NSObject elem in array) + { + if (elem.Equals(nso)) + { return true; } } @@ -129,10 +139,13 @@ namespace Claunia.PropertyList /// /// The index of the object, if it was found. -1 otherwise. /// The object to look for. - public int IndexOfObject(Object obj) { + public int IndexOfObject(Object obj) + { NSObject nso = NSObject.Wrap(obj); - for (int i = 0; i < array.Length; i++) { - if (array[i].Equals(nso)) { + for (int i = 0; i < array.Length; i++) + { + if (array[i].Equals(nso)) + { return i; } } @@ -147,10 +160,13 @@ namespace Claunia.PropertyList /// /// The index of the object, if it was found. -1 otherwise. /// The object to look for. - public int IndexOfIdenticalObject(Object obj) { + public int IndexOfIdenticalObject(Object obj) + { NSObject nso = NSObject.Wrap(obj); - for (int i = 0; i < array.Length; i++) { - if (array[i] == nso) { + for (int i = 0; i < array.Length; i++) + { + if (array[i] == nso) + { return i; } } @@ -161,7 +177,8 @@ namespace Claunia.PropertyList /// Returns the last object contained in this array. /// /// The value of the highest index in the array. - public NSObject LastObject() { + public NSObject LastObject() + { return array[array.Length - 1]; } @@ -171,7 +188,8 @@ namespace Claunia.PropertyList /// /// The new array containing the objects stored at the given indices. /// The indices of the objects. - public NSObject[] objectsAtIndexes(params int[] indexes) { + public NSObject[] objectsAtIndexes(params int[] indexes) + { NSObject[] result = new NSObject[indexes.Length]; Array.Sort(indexes); for (int i = 0; i < indexes.Length; i++) @@ -179,29 +197,37 @@ namespace Claunia.PropertyList return result; } - public override bool Equals(Object obj) { - if(obj.GetType().Equals(typeof(NSArray))) { - return Array.Equals(((NSArray) obj).GetArray(), this.array); - } else { + public override bool Equals(Object obj) + { + if (obj.GetType().Equals(typeof(NSArray))) + { + return Array.Equals(((NSArray)obj).GetArray(), this.array); + } + else + { NSObject nso = NSObject.Wrap(obj); - if(nso.GetType().Equals(typeof(NSArray))) { - return Array.Equals(((NSArray) nso).GetArray(), this.array); + if (nso.GetType().Equals(typeof(NSArray))) + { + return Array.Equals(((NSArray)nso).GetArray(), this.array); } } return false; } - public override int GetHashCode() { + public override int GetHashCode() + { int hash = 7; hash = 89 * hash + array.GetHashCode(); return hash; } - internal override void ToXml(StringBuilder xml, int level) { + internal override void ToXml(StringBuilder xml, int level) + { Indent(xml, level); xml.Append(""); xml.Append(NSObject.NEWLINE); - foreach (NSObject o in array) { + foreach (NSObject o in array) + { o.ToXml(xml, level + 1); xml.Append(NSObject.NEWLINE); } @@ -226,96 +252,103 @@ namespace Claunia.PropertyList }*/ - /** - * Generates a valid ASCII property list which has this NSArray as its - * root object. The generated property list complies with the format as - * described in - * Property List Programming Guide - Old-Style ASCII Property Lists. - * - * @return ASCII representation of this object. - * - public string toASCIIPropertyList() { + /// + /// Generates a valid ASCII property list which has this NSArray as its + /// root object. The generated property list complies with the format as + /// described in + /// Property List Programming Guide - Old-Style ASCII Property Lists. + /// + /// ASCII representation of this object. + public string ToASCIIPropertyList() + { StringBuilder ascii = new StringBuilder(); ToASCII(ascii, 0); ascii.Append(NEWLINE); return ascii.ToString(); } - /** - * Generates a valid ASCII property list in GnuStep format which has this - * NSArray as its root object. The generated property list complies with - * the format as described in - * GnuStep - NSPropertyListSerialization class documentation - * - * - * @return GnuStep ASCII representation of this object. - * - public string ToGnuStepASCIIPropertyList() { + /// + /// Generates a valid ASCII property list in GnuStep format which has this + /// NSArray as its root object. The generated property list complies with + /// the format as described in + /// GnuStep - NSPropertyListSerialization class documentation + /// + /// + /// GnuStep ASCII representation of this object. + public string ToGnuStepASCIIPropertyList() + { StringBuilder ascii = new StringBuilder(); ToASCIIGnuStep(ascii, 0); ascii.Append(NEWLINE); return ascii.ToString(); - }*/ - - protected override void ToASCII(StringBuilder ascii, int level) { - // TODO: Implement ASCIIPropertyListParser - /* - - indent(ascii, level); - ascii.append(ASCIIPropertyListParser.ARRAY_BEGIN_TOKEN); - int indexOfLastNewLine = ascii.lastIndexOf(NEWLINE); - for (int i = 0; i < array.length; i++) { - Class objClass = array[i].getClass(); - if ((objClass.equals(NSDictionary.class) || objClass.equals(NSArray.class) || objClass.equals(NSData.class)) - && indexOfLastNewLine != ascii.length()) { - ascii.append(NEWLINE); - indexOfLastNewLine = ascii.length(); - array[i].toASCII(ascii, level + 1); - } else { - if (i != 0) - ascii.append(" "); - array[i].toASCII(ascii, 0); - } - - if (i != array.length - 1) - ascii.append(ASCIIPropertyListParser.ARRAY_ITEM_DELIMITER_TOKEN); - - if (ascii.length() - indexOfLastNewLine > ASCII_LINE_LENGTH) { - ascii.append(NEWLINE); - indexOfLastNewLine = ascii.length(); - } - } - ascii.append(ASCIIPropertyListParser.ARRAY_END_TOKEN);*/ } - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { - // TODO: Implement ASCIIPropertyListParser - /* - indent(ascii, level); - ascii.append(ASCIIPropertyListParser.ARRAY_BEGIN_TOKEN); - int indexOfLastNewLine = ascii.lastIndexOf(NEWLINE); - for (int i = 0; i < array.length; i++) { - Class objClass = array[i].getClass(); - if ((objClass.equals(NSDictionary.class) || objClass.equals(NSArray.class) || objClass.equals(NSData.class)) - && indexOfLastNewLine != ascii.length()) { - ascii.append(NEWLINE); - indexOfLastNewLine = ascii.length(); - array[i].toASCIIGnuStep(ascii, level + 1); - } else { + internal override void ToASCII(StringBuilder ascii, int level) + { + Indent(ascii, level); + ascii.Append(ASCIIPropertyListParser.ARRAY_BEGIN_TOKEN); + int indexOfLastNewLine = ascii.ToString().LastIndexOf(NEWLINE); + for (int i = 0; i < array.Length; i++) + { + Type objClass = array[i].GetType(); + if ((objClass.Equals(typeof(NSDictionary)) || objClass.Equals(typeof(NSArray)) || objClass.Equals(typeof(NSData))) + && indexOfLastNewLine != ascii.Length) + { + ascii.Append(NEWLINE); + indexOfLastNewLine = ascii.Length; + array[i].ToASCII(ascii, level + 1); + } + else + { if (i != 0) - ascii.append(" "); - array[i].toASCIIGnuStep(ascii, 0); + ascii.Append(" "); + array[i].ToASCII(ascii, 0); } - if (i != array.length - 1) - ascii.append(ASCIIPropertyListParser.ARRAY_ITEM_DELIMITER_TOKEN); + if (i != array.Length - 1) + ascii.Append(ASCIIPropertyListParser.ARRAY_ITEM_DELIMITER_TOKEN); - if (ascii.length() - indexOfLastNewLine > ASCII_LINE_LENGTH) { - ascii.append(NEWLINE); - indexOfLastNewLine = ascii.length(); + if (ascii.Length - indexOfLastNewLine > ASCII_LINE_LENGTH) + { + ascii.Append(NEWLINE); + indexOfLastNewLine = ascii.Length; } } - ascii.append(ASCIIPropertyListParser.ARRAY_END_TOKEN);*/ + ascii.Append(ASCIIPropertyListParser.ARRAY_END_TOKEN); + } + + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) + { + Indent(ascii, level); + ascii.Append(ASCIIPropertyListParser.ARRAY_BEGIN_TOKEN); + int indexOfLastNewLine = ascii.ToString().LastIndexOf(NEWLINE); + for (int i = 0; i < array.Length; i++) + { + Type objClass = array[i].GetType(); + if ((objClass.Equals(typeof(NSDictionary)) || objClass.Equals(typeof(NSArray)) || objClass.Equals(typeof(NSData))) + && indexOfLastNewLine != ascii.Length) + { + ascii.Append(NEWLINE); + indexOfLastNewLine = ascii.Length; + array[i].ToASCIIGnuStep(ascii, level + 1); + } + else + { + if (i != 0) + ascii.Append(" "); + array[i].ToASCIIGnuStep(ascii, 0); + } + + if (i != array.Length - 1) + ascii.Append(ASCIIPropertyListParser.ARRAY_ITEM_DELIMITER_TOKEN); + + if (ascii.Length - indexOfLastNewLine > ASCII_LINE_LENGTH) + { + ascii.Append(NEWLINE); + indexOfLastNewLine = ascii.Length; + } + } + ascii.Append(ASCIIPropertyListParser.ARRAY_END_TOKEN); } } } diff --git a/plist-cil/NSData.cs b/plist-cil/NSData.cs index a04aa2d..bc0f2cc 100644 --- a/plist-cil/NSData.cs +++ b/plist-cil/NSData.cs @@ -145,28 +145,24 @@ namespace Claunia.PropertyList out.write(bytes); }*/ - protected override void ToASCII(StringBuilder ascii, int level) { - // TODO: Implement ASCIIPropertyListParser - /* - indent(ascii, level); - ascii.append(ASCIIPropertyListParser.DATA_BEGIN_TOKEN); - int indexOfLastNewLine = ascii.lastIndexOf(NEWLINE); - for (int i = 0; i < bytes.length; i++) { + internal override void ToASCII(StringBuilder ascii, int level) { + Indent(ascii, level); + ascii.Append(ASCIIPropertyListParser.DATA_BEGIN_TOKEN); + int indexOfLastNewLine = ascii.ToString().LastIndexOf(NEWLINE); + for (int i = 0; i < bytes.Length; i++) { int b = bytes[i] & 0xFF; - if (b < 16) - ascii.append("0"); - ascii.append(Integer.toHexString(b)); - if (ascii.length() - indexOfLastNewLine > ASCII_LINE_LENGTH) { - ascii.append(NEWLINE); - indexOfLastNewLine = ascii.length(); - } else if ((i + 1) % 2 == 0 && i != bytes.length - 1) { - ascii.append(" "); + ascii.Append(String.Format("{0:x2}", b)); + if (ascii.Length - indexOfLastNewLine > ASCII_LINE_LENGTH) { + ascii.Append(NEWLINE); + indexOfLastNewLine = ascii.Length; + } else if ((i + 1) % 2 == 0 && i != bytes.Length - 1) { + ascii.Append(" "); } } - ascii.append(ASCIIPropertyListParser.DATA_END_TOKEN);*/ + ascii.Append(ASCIIPropertyListParser.DATA_END_TOKEN); } - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) { ToASCII(ascii, level); } } diff --git a/plist-cil/NSDate.cs b/plist-cil/NSDate.cs index 7c08889..0dc683c 100644 --- a/plist-cil/NSDate.cs +++ b/plist-cil/NSDate.cs @@ -149,14 +149,14 @@ namespace Claunia.PropertyList return date.ToString(); } - protected override void ToASCII(StringBuilder ascii, int level) { + internal override void ToASCII(StringBuilder ascii, int level) { Indent(ascii, level); ascii.Append("\""); ascii.Append(MakeDateString(date)); ascii.Append("\""); } - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) { Indent(ascii, level); ascii.Append("<*D"); ascii.Append(MakeDateStringGnuStep(date)); diff --git a/plist-cil/NSDictionary.cs b/plist-cil/NSDictionary.cs index df4800d..f78fa03 100644 --- a/plist-cil/NSDictionary.cs +++ b/plist-cil/NSDictionary.cs @@ -317,60 +317,54 @@ namespace Claunia.PropertyList return ascii.ToString(); } - protected override void ToASCII(StringBuilder ascii, int level) { - // TODO: Implement ASCIIPropertyListParser - /* - indent(ascii, level); - ascii.append(ASCIIPropertyListParser.DICTIONARY_BEGIN_TOKEN); - ascii.append(NEWLINE); - String[] keys = allKeys(); - for (String key : keys) { - NSObject val = objectForKey(key); - indent(ascii, level + 1); - ascii.append("\""); - ascii.append(NSString.escapeStringForASCII(key)); - ascii.append("\" ="); - Class objClass = val.getClass(); - if (objClass.equals(NSDictionary.class) || objClass.equals(NSArray.class) || objClass.equals(NSData.class)) { - ascii.append(NEWLINE); - val.toASCII(ascii, level + 2); + internal override void ToASCII(StringBuilder ascii, int level) { + Indent(ascii, level); + ascii.Append(ASCIIPropertyListParser.DICTIONARY_BEGIN_TOKEN); + ascii.Append(NEWLINE); + foreach (string key in Keys) { + NSObject val = ObjectForKey(key); + Indent(ascii, level + 1); + ascii.Append("\""); + ascii.Append(NSString.EscapeStringForASCII(key)); + ascii.Append("\" ="); + Type objClass = val.GetType(); + if (objClass.Equals(typeof(NSDictionary)) || objClass.Equals(typeof(NSArray)) || objClass.Equals(typeof(NSData))) { + ascii.Append(NEWLINE); + val.ToASCII(ascii, level + 2); } else { - ascii.append(" "); - val.toASCII(ascii, 0); + ascii.Append(" "); + val.ToASCII(ascii, 0); } - ascii.append(ASCIIPropertyListParser.DICTIONARY_ITEM_DELIMITER_TOKEN); - ascii.append(NEWLINE); + ascii.Append(ASCIIPropertyListParser.DICTIONARY_ITEM_DELIMITER_TOKEN); + ascii.Append(NEWLINE); } - indent(ascii, level); - ascii.append(ASCIIPropertyListParser.DICTIONARY_END_TOKEN);*/ + Indent(ascii, level); + ascii.Append(ASCIIPropertyListParser.DICTIONARY_END_TOKEN); } - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { - // TODO: Implement ASCIIPropertyListParser - /* - indent(ascii, level); - ascii.append(ASCIIPropertyListParser.DICTIONARY_BEGIN_TOKEN); - ascii.append(NEWLINE); - String[] keys = dict.keySet().toArray(new String[dict.size()]); - for (String key : keys) { - NSObject val = objectForKey(key); - indent(ascii, level + 1); - ascii.append("\""); - ascii.append(NSString.escapeStringForASCII(key)); - ascii.append("\" ="); - Class objClass = val.getClass(); - if (objClass.equals(NSDictionary.class) || objClass.equals(NSArray.class) || objClass.equals(NSData.class)) { - ascii.append(NEWLINE); - val.toASCIIGnuStep(ascii, level + 2); + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) { + Indent(ascii, level); + ascii.Append(ASCIIPropertyListParser.DICTIONARY_BEGIN_TOKEN); + ascii.Append(NEWLINE); + foreach (string key in Keys) { + NSObject val = ObjectForKey(key); + Indent(ascii, level + 1); + ascii.Append("\""); + ascii.Append(NSString.EscapeStringForASCII(key)); + ascii.Append("\" ="); + Type objClass = val.GetType(); + if (objClass.Equals(typeof(NSDictionary)) || objClass.Equals(typeof(NSArray)) || objClass.Equals(typeof(NSData))) { + ascii.Append(NEWLINE); + val.ToASCIIGnuStep(ascii, level + 2); } else { - ascii.append(" "); - val.toASCIIGnuStep(ascii, 0); + ascii.Append(" "); + val.ToASCIIGnuStep(ascii, 0); } - ascii.append(ASCIIPropertyListParser.DICTIONARY_ITEM_DELIMITER_TOKEN); - ascii.append(NEWLINE); + ascii.Append(ASCIIPropertyListParser.DICTIONARY_ITEM_DELIMITER_TOKEN); + ascii.Append(NEWLINE); } - indent(ascii, level); - ascii.append(ASCIIPropertyListParser.DICTIONARY_END_TOKEN);*/ + Indent(ascii, level); + ascii.Append(ASCIIPropertyListParser.DICTIONARY_END_TOKEN); } #region IDictionary implementation diff --git a/plist-cil/NSNumber.cs b/plist-cil/NSNumber.cs index 3055a02..766341d 100644 --- a/plist-cil/NSNumber.cs +++ b/plist-cil/NSNumber.cs @@ -337,7 +337,7 @@ namespace Claunia.PropertyList } }*/ - protected override void ToASCII(StringBuilder ascii, int level) { + internal override void ToASCII(StringBuilder ascii, int level) { Indent(ascii, level); if (type == BOOLEAN) { ascii.Append(boolValue ? "YES" : "NO"); @@ -346,7 +346,7 @@ namespace Claunia.PropertyList } } - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) { Indent(ascii, level); switch (type) { case INTEGER: { diff --git a/plist-cil/NSObject.cs b/plist-cil/NSObject.cs index 4af035c..497f7d4 100644 --- a/plist-cil/NSObject.cs +++ b/plist-cil/NSObject.cs @@ -57,7 +57,7 @@ namespace Claunia.PropertyList /// ASCII property lists. But this number is only a guideline it is not /// guaranteed that it will not be overstepped. /// - readonly static int ASCII_LINE_LENGTH = 80; + internal readonly static int ASCII_LINE_LENGTH = 80; /// /// Generates the XML representation of the object (without XML headers or enclosing plist-tags). @@ -107,7 +107,7 @@ namespace Claunia.PropertyList /// /// The StringBuilder onto which the ASCII representation is appended. /// The indentation level of the object. - protected abstract void ToASCII(StringBuilder ascii, int level); + internal abstract void ToASCII(StringBuilder ascii, int level); /// /// Generates the ASCII representation of this object in the GnuStep format. @@ -115,7 +115,7 @@ namespace Claunia.PropertyList /// /// The StringBuilder onto which the ASCII representation is appended. /// The indentation level of the object. - protected abstract void ToASCIIGnuStep(StringBuilder ascii, int level); + internal abstract void ToASCIIGnuStep(StringBuilder ascii, int level); /// /// Helper method that adds correct identation to the xml output. diff --git a/plist-cil/NSSet.cs b/plist-cil/NSSet.cs index c048bf7..6db621b 100644 --- a/plist-cil/NSSet.cs +++ b/plist-cil/NSSet.cs @@ -284,15 +284,14 @@ namespace Claunia.PropertyList /// /// The ASCII file string builder /// The indentation level - protected override void ToASCII(StringBuilder ascii, int level) { - // TODO: Implement ASCIIPropertyListParse -/* Indent(ascii, level); + internal override void ToASCII(StringBuilder ascii, int level) { + Indent(ascii, level); NSObject[] array = AllObjects(); ascii.Append(ASCIIPropertyListParser.ARRAY_BEGIN_TOKEN); - int indexOfLastNewLine = ascii.lastIndexOf(NEWLINE); + int indexOfLastNewLine = ascii.ToString().LastIndexOf(NEWLINE); for (int i = 0; i < array.Length; i++) { Type objClass = array[i].GetType(); - if ((objClass.Equals(NSDictionary.GetType()) || objClass.Equals(NSArray.GetType()) || objClass.Equals(NSData.GetType())) + if ((objClass.Equals(typeof(NSDictionary)) || objClass.Equals(typeof(NSArray)) || objClass.Equals(typeof(NSData))) && indexOfLastNewLine != ascii.Length) { ascii.Append(NEWLINE); indexOfLastNewLine = ascii.Length; @@ -311,7 +310,7 @@ namespace Claunia.PropertyList indexOfLastNewLine = ascii.Length; } } - ascii.append(ASCIIPropertyListParser.ARRAY_END_TOKEN);*/ + ascii.Append(ASCIIPropertyListParser.ARRAY_END_TOKEN); } /// @@ -321,35 +320,33 @@ namespace Claunia.PropertyList /// /// The ASCII file string builder /// The indentation level - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { - // TODO: Implement ASCIIPropertyListParse - /* - indent(ascii, level); - NSObject[] array = allObjects(); - ascii.append(ASCIIPropertyListParser.ARRAY_BEGIN_TOKEN); - int indexOfLastNewLine = ascii.lastIndexOf(NEWLINE); - for (int i = 0; i < array.length; i++) { - Class objClass = array[i].getClass(); - if ((objClass.equals(NSDictionary.class) || objClass.equals(NSArray.class) || objClass.equals(NSData.class)) - && indexOfLastNewLine != ascii.length()) { - ascii.append(NEWLINE); - indexOfLastNewLine = ascii.length(); - array[i].toASCIIGnuStep(ascii, level + 1); + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) { + Indent(ascii, level); + NSObject[] array = AllObjects(); + ascii.Append(ASCIIPropertyListParser.ARRAY_BEGIN_TOKEN); + int indexOfLastNewLine = ascii.ToString().LastIndexOf(NEWLINE); + for (int i = 0; i < array.Length; i++) { + Type objClass = array[i].GetType(); + if ((objClass.Equals(typeof(NSDictionary)) || objClass.Equals(typeof(NSArray)) || objClass.Equals(typeof(NSData))) + && indexOfLastNewLine != ascii.Length) { + ascii.Append(NEWLINE); + indexOfLastNewLine = ascii.Length; + array[i].ToASCIIGnuStep(ascii, level + 1); } else { if (i != 0) - ascii.append(" "); - array[i].toASCIIGnuStep(ascii, 0); + ascii.Append(" "); + array[i].ToASCIIGnuStep(ascii, 0); } - if (i != array.length - 1) - ascii.append(ASCIIPropertyListParser.ARRAY_ITEM_DELIMITER_TOKEN); + if (i != array.Length - 1) + ascii.Append(ASCIIPropertyListParser.ARRAY_ITEM_DELIMITER_TOKEN); - if (ascii.length() - indexOfLastNewLine > ASCII_LINE_LENGTH) { - ascii.append(NEWLINE); - indexOfLastNewLine = ascii.length(); + if (ascii.Length - indexOfLastNewLine > ASCII_LINE_LENGTH) { + ascii.Append(NEWLINE); + indexOfLastNewLine = ascii.Length; } } - ascii.append(ASCIIPropertyListParser.ARRAY_END_TOKEN);*/ + ascii.Append(ASCIIPropertyListParser.ARRAY_END_TOKEN); } } } diff --git a/plist-cil/NSString.cs b/plist-cil/NSString.cs index 9eb5df0..67f634c 100644 --- a/plist-cil/NSString.cs +++ b/plist-cil/NSString.cs @@ -183,7 +183,7 @@ namespace Claunia.PropertyList out.write(bytes); }*/ - protected override void ToASCII(StringBuilder ascii, int level) { + internal override void ToASCII(StringBuilder ascii, int level) { Indent(ascii, level); ascii.Append("\""); //According to https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/PropertyLists/OldStylePlists/OldStylePLists.html @@ -194,25 +194,19 @@ namespace Claunia.PropertyList ascii.Append("\""); } - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) { Indent(ascii, level); ascii.Append("\""); ascii.Append(EscapeStringForASCII(content)); ascii.Append("\""); } - /** - * - * - * @param s - * @return The unescaped string. - */ /// /// Escapes a string for use in ASCII property lists. /// /// The unescaped string. /// S. - static string EscapeStringForASCII(string s) { + internal static string EscapeStringForASCII(string s) { string outString = ""; char[] cArray = s.ToCharArray(); for (int i = 0; i < cArray.Length; i++) { diff --git a/plist-cil/PropertyListParser.cs b/plist-cil/PropertyListParser.cs index c47e62d..e711e62 100644 --- a/plist-cil/PropertyListParser.cs +++ b/plist-cil/PropertyListParser.cs @@ -111,7 +111,7 @@ namespace Claunia.PropertyList /// a maximum count. /// /// The Stream pointing to the data that should be stored in the array. - static byte[] ReadAll(Stream fs) { + internal static byte[] ReadAll(Stream fs) { MemoryStream outputStream = new MemoryStream(); byte[] buf = new byte[512]; int read = 512; @@ -149,8 +149,7 @@ namespace Claunia.PropertyList // TODO: Implement XMLPropertyListParser //return XMLPropertyListParser.parse(f); case TYPE_ASCII: - // TODO: Implement ASCIIPropertyListParser - //return ASCIIPropertyListParser.parse(f); + return ASCIIPropertyListParser.Parse(f); default: throw new PropertyListFormatException("The given file is not a property list of a supported format."); } @@ -170,8 +169,7 @@ namespace Claunia.PropertyList // TODO: Implement XMLPropertyListParser //return XMLPropertyListParser.parse(bytes); case TYPE_ASCII: - // TODO: Implement ASCIIPropertyListParser - //return ASCIIPropertyListParser.parse(bytes); + return ASCIIPropertyListParser.Parse(bytes); default: throw new PropertyListFormatException("The given data is not a property list of a supported format."); } @@ -287,8 +285,7 @@ namespace Claunia.PropertyList Directory.CreateDirectory(parent); Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); StreamWriter w = new StreamWriter(fous, Encoding.ASCII); - // TODO: Implement ASCIIPropertyListParser - //w.Write(root.ToASCIIPropertyList()); + w.Write(root.ToASCIIPropertyList()); w.Close(); fous.Close(); } @@ -341,8 +338,7 @@ namespace Claunia.PropertyList Directory.CreateDirectory(parent); Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); StreamWriter w = new StreamWriter(fous, Encoding.ASCII); - // TODO: Implement ASCIIPropertyListParser - //w.Write(root.toGnuStepASCIIPropertyList()); + w.Write(root.ToGnuStepASCIIPropertyList()); w.Close(); fous.Close(); } diff --git a/plist-cil/UID.cs b/plist-cil/UID.cs index df8257d..a7f5156 100644 --- a/plist-cil/UID.cs +++ b/plist-cil/UID.cs @@ -81,7 +81,7 @@ namespace Claunia.PropertyList out.write(bytes); }*/ - protected override void ToASCII(StringBuilder ascii, int level) { + internal override void ToASCII(StringBuilder ascii, int level) { Indent(ascii, level); ascii.Append("\""); for (int i = 0; i < bytes.Length; i++) { @@ -91,7 +91,7 @@ namespace Claunia.PropertyList ascii.Append("\""); } - protected override void ToASCIIGnuStep(StringBuilder ascii, int level) { + internal override void ToASCIIGnuStep(StringBuilder ascii, int level) { ToASCII(ascii, level); } } diff --git a/plist-cil/plist-cil.csproj b/plist-cil/plist-cil.csproj index a0f3303..7d8feb5 100644 --- a/plist-cil/plist-cil.csproj +++ b/plist-cil/plist-cil.csproj @@ -44,6 +44,7 @@ +