Coverage Report - net.wotonomy.foundation.NSPropertyListSerialization
 
Classes in this File Line Coverage Branch Coverage Complexity
NSPropertyListSerialization
12% 
19% 
10.25
 
 1  
 
 2  
 package net.wotonomy.foundation;
 3  
 
 4  1
 public class NSPropertyListSerialization {
 5  
 
 6  
     public static final int PLIST_ARRAY = 0;
 7  
     public static final int PLIST_DICTIONARY = 1;
 8  
     public static final int PLIST_DATA = 2;
 9  
     public static final int PLIST_STRING = 3;
 10  
 
 11  10
     public static final char[] TOKEN_BEGIN = new char[]{
 12  1
         '(', '{', '<', '"'
 13  
     };
 14  10
     public static final char[] TOKEN_END = new char[]{
 15  1
         ')', '}', '>', '"'
 16  
     };
 17  10
     public static final char[] QUOTING_CHARS = new char[]{
 18  1
             ':', '/', '-', '.', '\\'
 19  
     };
 20  
 
 21  
     private NSPropertyListSerialization() {
 22  0
         super();
 23  0
     }
 24  
 
 25  
     /** Creates a NSArray object from a string representation.
 26  
         @s The string representation of a NSArray object. */
 27  
     public static NSArray arrayForString(String s) {
 28  0
         s = s.trim();
 29  0
         if (!(s.charAt(0) == TOKEN_BEGIN[PLIST_ARRAY] && s.charAt(s.length()-1) == TOKEN_END[PLIST_ARRAY]))
 30  0
             return null;
 31  0
         NSMutableArray arr = new NSMutableArray();
 32  0
         int pos = 1;
 33  0
         int valbegin = -1;
 34  0
         while (pos < s.length()) {
 35  0
             char c = s.charAt(pos);
 36  0
             int tokenCount = 0;
 37  0
             int what = 0;
 38  0
             for (int i = 0 ; i < TOKEN_BEGIN.length; i++) {
 39  0
                 if (c == TOKEN_BEGIN[i]) {
 40  0
                     tokenCount = 1;
 41  0
                     what = i;
 42  0
                     break;
 43  
                 }
 44  
             }
 45  0
             if (tokenCount > 0) {
 46  
                 //mark it
 47  0
                 int quote = pos;
 48  
                 //find the closing token
 49  
                 do {
 50  0
                     pos++;
 51  
                                         try {
 52  0
                                                 c = s.charAt(pos);
 53  0
                                         } catch (StringIndexOutOfBoundsException ex) {
 54  0
                                                 throw new IllegalArgumentException("Could not parse property list; unclosed token '" + TOKEN_BEGIN[what] + "'");
 55  0
                                         }
 56  0
                                         if (c == '"' && what == PLIST_STRING) {
 57  0
                                                 if (pos > 0 && s.charAt(pos-1) != '\\') {
 58  0
                                                         tokenCount--;
 59  0
                                                 }
 60  0
                                         } else if (c == TOKEN_BEGIN[what])
 61  0
                         tokenCount++;
 62  0
                     else if (c == TOKEN_END[what])
 63  0
                         tokenCount--;
 64  0
                 } while (tokenCount > 0);
 65  0
                 arr.addObject(propertyListFromString(s.substring(quote, pos+1)));
 66  0
                 valbegin = -1;
 67  
                 //advance to the next position
 68  0
                 do {
 69  0
                     pos++;
 70  0
                     c = s.charAt(pos);
 71  0
                 } while (Character.isWhitespace(c));
 72  
             }
 73  0
             if (c == ',' || c ==')') {
 74  0
                 if (valbegin > 0) {
 75  0
                     arr.addObject(s.substring(valbegin, pos).trim());
 76  0
                     valbegin = -1;
 77  0
                 }
 78  0
             } else if (!Character.isWhitespace(c)) {
 79  0
                 if (valbegin < 0) {
 80  0
                     valbegin = pos;
 81  
                 }
 82  
             }
 83  0
             pos++;
 84  0
         }
 85  0
         return arr;
 86  
     }
 87  
 
 88  
     /** Creates a NSDictionary instance from a string representation.
 89  
         @s The string representation of a NSDictionary. */
 90  
     public static NSDictionary dictionaryForString(String s) {
 91  0
         s = s.trim();
 92  0
         if (!(s.charAt(0) == TOKEN_BEGIN[PLIST_DICTIONARY] && s.charAt(s.length()-1) == TOKEN_END[PLIST_DICTIONARY]))
 93  0
             return null;
 94  0
         NSMutableDictionary d = new NSMutableDictionary();
 95  0
         int pos = 1;
 96  0
         boolean parsing = true;
 97  0
         Object key = null;
 98  0
         int valbegin = -1;
 99  0
         while (pos < s.length()) {
 100  
             //look for an opening token
 101  0
             char c = s.charAt(pos);
 102  0
             int tokenCount = 0;
 103  0
             int what = 0;
 104  0
             for (int i = 0 ; i < TOKEN_BEGIN.length; i++) {
 105  0
                 if (c == TOKEN_BEGIN[i]) {
 106  0
                     tokenCount = 1;
 107  0
                     what = i;
 108  0
                     break;
 109  
                 }
 110  
             }
 111  0
             if (tokenCount > 0) {
 112  
                 //mark it
 113  0
                 int quote = pos;
 114  
                 //find the closing token
 115  
                 do {
 116  0
                     pos++;
 117  
                     try {
 118  0
                                                 c = s.charAt(pos);
 119  0
                     } catch (StringIndexOutOfBoundsException ex) {
 120  0
                             throw new IllegalArgumentException("Could not parse property list; unclosed token '" + TOKEN_BEGIN[what] + "'");
 121  0
                     }
 122  0
                     if (c == '"' && what == PLIST_STRING) {
 123  0
                             if (pos > 0 && s.charAt(pos-1) != '\\') {
 124  0
                                     tokenCount--;
 125  0
                             }
 126  0
                     } else if (c == TOKEN_BEGIN[what])
 127  0
                         tokenCount++;
 128  0
                     else if (c == TOKEN_END[what])
 129  0
                         tokenCount--;
 130  0
                 } while (tokenCount > 0);
 131  0
                 if (key == null) {
 132  0
                     key = propertyListFromString(s.substring(quote, pos+1));
 133  0
                 } else {
 134  0
                     d.setObjectForKey(propertyListFromString(s.substring(quote, pos+1)), key);
 135  0
                     key = null;
 136  
                 }
 137  0
                 valbegin = -1;
 138  
                 //advance to the next position
 139  0
                 do {
 140  0
                     pos++;
 141  0
                     c = s.charAt(pos);
 142  0
                 } while (Character.isWhitespace(c));
 143  
             }
 144  0
             if (c == ';' || c == '=' || c == '}') {
 145  0
                 if (valbegin > 0) {
 146  0
                     if (key == null) {
 147  0
                         key = s.substring(valbegin, pos).trim();
 148  0
                     } else {
 149  0
                         d.setObjectForKey(s.substring(valbegin, pos).trim(), key);
 150  0
                         key = null;
 151  
                     }
 152  0
                     valbegin = -1;
 153  0
                 }
 154  0
             } else if (!Character.isWhitespace(c)) {
 155  0
                 if (valbegin < 0) {
 156  0
                     valbegin = pos;
 157  
                 }
 158  
             }
 159  0
             pos++;
 160  0
         }
 161  0
         return d;
 162  
     }
 163  
 
 164  
     public static boolean booleanForString(String s) {
 165  0
         return s.trim().toLowerCase().equals("true");
 166  
     }
 167  
 
 168  
     /** Creates a NSData instance from a string representation.
 169  
         @s The string representation of a NSData object. */
 170  
     public static NSData dataFromPropertyList(String s) {
 171  0
         String hex = "0123456789ABCDEF";
 172  0
         s = s.trim();
 173  0
         if (!(s.charAt(0) == TOKEN_BEGIN[PLIST_DATA] && s.charAt(s.length()-1) == TOKEN_END[PLIST_DATA]))
 174  0
             return null;
 175  0
         int pos = 1;
 176  0
         java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
 177  0
         while (pos < s.length()-1) {
 178  0
             char c1 = s.charAt(pos);
 179  0
             while (c1 == ' ') {
 180  0
                 pos++;
 181  0
                 if (pos == s.length()-1)
 182  0
                     return new NSData(bout.toByteArray());
 183  0
                 c1 = s.charAt(pos);
 184  0
             }
 185  0
             if (hex.indexOf(c1) < 0)
 186  0
                 throw new IllegalArgumentException("The string does not represent a NSData object (" + s + ", pos " + pos + ")");
 187  0
             pos++;
 188  0
             char c2 = s.charAt(pos);
 189  0
             if (hex.indexOf(c2) < 0)
 190  0
                 throw new IllegalArgumentException("The string does not represent a NSData object (" + s + ")");
 191  0
             int x = (hex.indexOf(c1) << 4) | hex.indexOf(c2);
 192  0
             bout.write(x);
 193  0
             pos++;
 194  0
         }
 195  0
         return new NSData(bout.toByteArray());
 196  
     }
 197  
 
 198  
     public static int intForString(String s) {
 199  0
         return Integer.parseInt(s);
 200  
     }
 201  
 
 202  
     /** Returns the string representation of a property list.
 203  
         @plist The property list. It can be a String, NSData, NSArray, NSDictionary. */
 204  
     public static String stringForPropertyList(Object plist) {
 205  27
         if (plist == null)
 206  0
             return "";
 207  27
         if (plist instanceof NSArray || plist instanceof NSDictionary || plist instanceof NSData)
 208  0
             return plist.toString();
 209  27
         String x = plist.toString();
 210  27
         boolean quote = false;
 211  72
         for (int i = 0; i < x.length(); i++) {
 212  45
                 char c = x.charAt(i);
 213  225
                 for (int z = 0; z < TOKEN_BEGIN.length; z++) {
 214  180
                         if (c == TOKEN_BEGIN[z] || c == TOKEN_END[z])
 215  0
                                 quote = true;
 216  
                 }
 217  45
                 if (!quote) {
 218  270
                         for (int z = 0; z < QUOTING_CHARS.length; z++) {
 219  225
                                 if (c == QUOTING_CHARS[z])
 220  0
                                         quote = true;
 221  
                         }
 222  
                 }
 223  45
             if (!quote && Character.isWhitespace(c)) {
 224  0
                 quote = true;
 225  0
                 i = x.length();
 226  
             }
 227  
         }
 228  27
         if (quote)
 229  0
             return "\"" + x + "\"";
 230  27
         return x;
 231  
     }
 232  
 
 233  
     /** Returns an property list created from a string representation.
 234  
         @s The string with a representation of a property list.
 235  
         @returns A property list object; either a NSData, NSArray, NSDictionary, or a String. */
 236  
     public static Object propertyListFromString(String s) {
 237  0
         s = s.trim();
 238  0
         int type = -1;
 239  0
         for (int i = 0; i < TOKEN_BEGIN.length; i++) {
 240  0
             if (TOKEN_BEGIN[i] == s.charAt(0)) {
 241  0
                 if (TOKEN_END[i] == s.charAt(s.length()-1))
 242  0
                     type = i;
 243  
             }
 244  
         }
 245  0
         switch (type) {
 246  
             case PLIST_DATA:
 247  0
                 return dataFromPropertyList(s);
 248  
             case PLIST_ARRAY:
 249  0
                 return arrayForString(s);
 250  
             case PLIST_DICTIONARY:
 251  0
                 return dictionaryForString(s);
 252  
             case PLIST_STRING:
 253  0
                     if (s.equals("\"\""))
 254  0
                             return "";
 255  0
                 return s.substring(1, s.length()-1);
 256  
         }
 257  0
         return s;
 258  
     }
 259  
 
 260  
     /*
 261  
      * $Log$
 262  
      * Revision 1.2  2006/02/16 13:15:00  cgruber
 263  
      * Check in all sources in eclipse-friendly maven-enabled packages.
 264  
      *
 265  
      * Revision 1.5  2003/08/11 18:18:08  chochos
 266  
      * improved encoding of strings, removed warnings
 267  
      *
 268  
      * Revision 1.4  2003/08/11 17:33:45  chochos
 269  
      * Implemented detection of escaped quotes (\"). improved quoting strings when converting property lists to strings.
 270  
      *
 271  
      * Revision 1.3  2003/08/04 23:50:55  chochos
 272  
      * propertyListForString() now works. dictionaryForString and arrayForString can parse complex structures with nested arrays and dictionaries.
 273  
      *
 274  
      */
 275  
 }