mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
676 lines
22 KiB
JavaScript
676 lines
22 KiB
JavaScript
/*
|
|
* CFPropertyList.js
|
|
* Objective-J
|
|
*
|
|
* Created by Francisco Tolmasky.
|
|
* Copyright 2008-2010, 280 North, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
|
|
var OBJECT_COUNT = 0;
|
|
|
|
GLOBAL(objj_generateObjectUID) = function()
|
|
{
|
|
return OBJECT_COUNT++;
|
|
}
|
|
|
|
GLOBAL(CFPropertyList) = function()
|
|
{
|
|
this._UID = objj_generateObjectUID();
|
|
}
|
|
|
|
// We are really liberal when accepting DOCTYPEs.
|
|
CFPropertyList.DTDRE = /^\s*(?:<\?\s*xml\s+version\s*=\s*\"1.0\"[^>]*\?>\s*)?(?:<\!DOCTYPE[^>]*>\s*)?/i
|
|
CFPropertyList.XMLRE = /^\s*(?:<\?\s*xml\s+version\s*=\s*\"1.0\"[^>]*\?>\s*)?(?:<\!DOCTYPE[^>]*>\s*)?<\s*plist[^>]*\>/i;
|
|
|
|
CFPropertyList.FormatXMLDTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
|
|
CFPropertyList.Format280NorthMagicNumber = "280NPLIST";
|
|
|
|
// Serialization Formats
|
|
|
|
CFPropertyList.FormatOpenStep = 1,
|
|
CFPropertyList.FormatXML_v1_0 = 100,
|
|
CFPropertyList.FormatBinary_v1_0 = 200,
|
|
CFPropertyList.Format280North_v1_0 = -1000;
|
|
|
|
CFPropertyList.sniffedFormatOfString = function(/*String*/ aString)
|
|
{
|
|
// Check if this is an XML Plist.
|
|
if (aString.match(CFPropertyList.XMLRE))
|
|
return CFPropertyList.FormatXML_v1_0;
|
|
|
|
if (aString.substr(0, CFPropertyList.Format280NorthMagicNumber.length) === CFPropertyList.Format280NorthMagicNumber)
|
|
return CFPropertyList.Format280North_v1_0;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// Serialization
|
|
|
|
CFPropertyList.dataFromPropertyList = function(/*CFPropertyList*/ aPropertyList, /*Format*/ aFormat)
|
|
{
|
|
var data = new CFMutableData();
|
|
|
|
data.setRawString(CFPropertyList.stringFromPropertyList(aPropertyList, aFormat));
|
|
|
|
return data;
|
|
}
|
|
|
|
CFPropertyList.stringFromPropertyList = function(/*CFPropertyList*/ aPropertyList, /*Format*/ aFormat)
|
|
{
|
|
if (!aFormat)
|
|
aFormat = CFPropertyList.Format280North_v1_0;
|
|
|
|
var serializers = CFPropertyListSerializers[aFormat];
|
|
|
|
return serializers["start"]() +
|
|
serializePropertyList(aPropertyList, serializers) +
|
|
serializers["finish"]();
|
|
}
|
|
|
|
#ifdef COMMONJS
|
|
var fs = require("fs");
|
|
|
|
CFPropertyList.readPropertyListFromFile = function(/*String*/ aFilePath)
|
|
{
|
|
return CFPropertyList.propertyListFromString(fs.readFileSync(aFilePath, { encoding: "utf8" }));
|
|
//return CFPropertyList.propertyListFromString(FILE.read(aFilePath, { charset:"UTF-8" }));
|
|
}
|
|
|
|
CFPropertyList.writePropertyListToFile = function(/*CFPropertyList*/ aPropertyList, /*String*/ aFilePath, /*Format*/ aFormat)
|
|
{
|
|
return FILE.write(aFilePath, CFPropertyList.stringFromPropertyList(aPropertyList, aFormat), { charset:"UTF-8" });
|
|
}
|
|
CFPropertyList.modifyPlist = function(/*String*/ aFilePath, /*Function*/ aCallback, /*String*/ aFormat)
|
|
{
|
|
var string = FILE.read(aFilePath, { charset:"UTF-8" });
|
|
var format = CFPropertyList.sniffedFormatOfString(string);
|
|
var plist = CFPropertyList.propertyListFromString(string, format);
|
|
|
|
aCallback(plist);
|
|
|
|
CFPropertyList.writePropertyListToFile(plist, aFilePath, aFormat || format);
|
|
}
|
|
#endif
|
|
|
|
function serializePropertyList(/*CFPropertyList*/ aPropertyList, /*Object*/ serializers)
|
|
{
|
|
var type = typeof aPropertyList,
|
|
valueOf = aPropertyList.valueOf(),
|
|
typeValueOf = typeof valueOf;
|
|
|
|
if (type !== typeValueOf)
|
|
{
|
|
type = typeValueOf;
|
|
aPropertyList = valueOf;
|
|
}
|
|
|
|
if (aPropertyList === YES || aPropertyList === NO)
|
|
type = "boolean";
|
|
|
|
else if (type === "number")
|
|
{
|
|
// A number like 3.4028234663852885e+54 should not be written as an integer, even that it is
|
|
// an integer - it'd be awfully long if written by expanding it. Worse, if written as an
|
|
// integer with scientific notation the parseInt() used to read it back will parse it as
|
|
// just 3, thereby wasting many hours of sanity when you're trying to nib2cib a table and
|
|
// columns are mysteriously showing up 3 pixels wide.
|
|
if (FLOOR(aPropertyList) === aPropertyList && ("" + aPropertyList).indexOf('e') == -1)
|
|
type = "integer";
|
|
else
|
|
type = "real";
|
|
}
|
|
|
|
else if (type !== "string")
|
|
{
|
|
if (aPropertyList.slice)
|
|
type = "array";
|
|
|
|
else
|
|
type = "dictionary";
|
|
}
|
|
|
|
return serializers[type](aPropertyList, serializers);
|
|
}
|
|
|
|
var CFPropertyListSerializers = { };
|
|
|
|
CFPropertyListSerializers[CFPropertyList.FormatXML_v1_0] =
|
|
{
|
|
"start": function()
|
|
{
|
|
return CFPropertyList.FormatXMLDTD + "<plist version = \"1.0\">";
|
|
},
|
|
|
|
"finish": function()
|
|
{
|
|
return "</plist>";
|
|
},
|
|
|
|
"string": function(/*String*/ aString)
|
|
{
|
|
return "<string>" + encodeHTMLComponent(aString) + "</string>";
|
|
},
|
|
|
|
"boolean" : function(/*Boolean*/ aBoolean)
|
|
{
|
|
return aBoolean ? "<true/>" : "<false/>";
|
|
},
|
|
|
|
"integer": function(/*Integer*/ anInteger)
|
|
{
|
|
return "<integer>" + anInteger + "</integer>";
|
|
},
|
|
|
|
"real": function(/*Float*/ aFloat)
|
|
{
|
|
return "<real>" + aFloat + "</real>";
|
|
},
|
|
|
|
"array": function(/*Array*/ anArray, /*Object*/ serializers)
|
|
{
|
|
var index = 0,
|
|
count = anArray.length,
|
|
string = "<array>";
|
|
|
|
for (; index < count; ++index)
|
|
string += serializePropertyList(anArray[index], serializers);
|
|
|
|
return string + "</array>";
|
|
},
|
|
|
|
"dictionary": function(/*CFDictionary*/ aDictionary, /*Object*/ serializers)
|
|
{
|
|
var keys = aDictionary._keys,
|
|
index = 0,
|
|
count = keys.length,
|
|
string = "<dict>";
|
|
|
|
for (; index < count; ++index)
|
|
{
|
|
var key = keys[index];
|
|
|
|
string += "<key>" + key + "</key>";
|
|
string += serializePropertyList(aDictionary.valueForKey(key), serializers);
|
|
}
|
|
|
|
return string + "</dict>";
|
|
}
|
|
}
|
|
|
|
// 280 North Plist Format
|
|
|
|
var ARRAY_MARKER = "A",
|
|
DICTIONARY_MARKER = "D",
|
|
FLOAT_MARKER = "f",
|
|
INTEGER_MARKER = "d",
|
|
STRING_MARKER = "S",
|
|
TRUE_MARKER = "T",
|
|
FALSE_MARKER = "F",
|
|
KEY_MARKER = "K",
|
|
END_MARKER = "E";
|
|
|
|
CFPropertyListSerializers[CFPropertyList.Format280North_v1_0] =
|
|
{
|
|
"start": function()
|
|
{
|
|
return CFPropertyList.Format280NorthMagicNumber + ";1.0;";
|
|
},
|
|
|
|
"finish": function()
|
|
{
|
|
return "";
|
|
},
|
|
|
|
"string" : function(/*String*/ aString)
|
|
{
|
|
return STRING_MARKER + ';' + aString.length + ';' + aString;
|
|
},
|
|
|
|
"boolean" : function(/*Boolean*/ aBoolean)
|
|
{
|
|
return (aBoolean ? TRUE_MARKER : FALSE_MARKER) + ';';
|
|
},
|
|
|
|
"integer": function(/*Integer*/ anInteger)
|
|
{
|
|
var string = "" + anInteger;
|
|
|
|
return INTEGER_MARKER + ';' + string.length + ';' + string;
|
|
},
|
|
|
|
"real": function(/*Float*/ aFloat)
|
|
{
|
|
var string = "" + aFloat;
|
|
|
|
return FLOAT_MARKER + ';' + string.length + ';' + string;
|
|
},
|
|
|
|
"array": function(/*Array*/ anArray, /*Object*/ serializers)
|
|
{
|
|
var index = 0,
|
|
count = anArray.length,
|
|
string = ARRAY_MARKER + ';';
|
|
|
|
for (; index < count; ++index)
|
|
string += serializePropertyList(anArray[index], serializers);
|
|
|
|
return string + END_MARKER + ';';
|
|
},
|
|
|
|
"dictionary": function(/*CFDictionary*/ aDictionary, /*Object*/ serializers)
|
|
{
|
|
var keys = aDictionary._keys,
|
|
index = 0,
|
|
count = keys.length,
|
|
string = DICTIONARY_MARKER +';';
|
|
|
|
for (; index < count; ++index)
|
|
{
|
|
var key = keys[index];
|
|
|
|
string += KEY_MARKER + ';' + key.length + ';' + key;
|
|
string += serializePropertyList(aDictionary.valueForKey(key), serializers);
|
|
}
|
|
|
|
return string + END_MARKER + ';';
|
|
}
|
|
}
|
|
|
|
// Deserialization
|
|
|
|
var XML_XML = "xml",
|
|
XML_DOCUMENT = "#document",
|
|
|
|
PLIST_PLIST = "plist",
|
|
PLIST_KEY = "key",
|
|
PLIST_DICTIONARY = "dict",
|
|
PLIST_ARRAY = "array",
|
|
PLIST_STRING = "string",
|
|
PLIST_DATE = "date",
|
|
PLIST_BOOLEAN_TRUE = "true",
|
|
PLIST_BOOLEAN_FALSE = "false",
|
|
PLIST_NUMBER_REAL = "real",
|
|
PLIST_NUMBER_INTEGER = "integer",
|
|
PLIST_DATA = "data";
|
|
|
|
#define NODE_NAME(anXMLNode) (String(anXMLNode.nodeName))
|
|
#define NODE_TYPE(anXMLNode) (anXMLNode.nodeType)
|
|
#define TEXT_CONTENT(anXMLNode) (anXMLNode.textContent || (anXMLNode.textContent !== "" && textContent([anXMLNode])))
|
|
#define FIRST_CHILD(anXMLNode) (anXMLNode.firstChild)
|
|
#define NEXT_SIBLING(anXMLNode) (anXMLNode.nextSibling)
|
|
#define PARENT_NODE(anXMLNode) (anXMLNode.parentNode)
|
|
#define DOCUMENT_ELEMENT(aDocument) (aDocument && aDocument.documentElement)
|
|
|
|
#define HAS_ATTRIBUTE_VALUE(anXMLNode, anAttributeName, aValue) (anXMLNode.getAttribute(anAttributeName) === aValue)
|
|
|
|
#define IS_OF_TYPE(anXMLNode, aType) (NODE_NAME(anXMLNode) === aType)
|
|
#define IS_PLIST(anXMLNode) IS_OF_TYPE(anXMLNode, PLIST_PLIST)
|
|
|
|
#define IS_WHITESPACE(anXMLNode) (NODE_TYPE(anXMLNode) === 8 || NODE_TYPE(anXMLNode) === 3 || NODE_TYPE(anXMLNode) === 7)
|
|
#define IS_DOCUMENTTYPE(anXMLNode) (NODE_TYPE(anXMLNode) === 10)
|
|
|
|
#define PLIST_NEXT_SIBLING(anXMLNode) while ((anXMLNode = NEXT_SIBLING(anXMLNode)) && IS_WHITESPACE(anXMLNode));
|
|
#define PLIST_FIRST_CHILD(anXMLNode) { anXMLNode = FIRST_CHILD(anXMLNode); if (anXMLNode != NULL && IS_WHITESPACE(anXMLNode)) PLIST_NEXT_SIBLING(anXMLNode) }
|
|
|
|
var textContent = function(nodes)
|
|
{
|
|
var text = "",
|
|
index = 0,
|
|
count = nodes.length;
|
|
|
|
for (; index < count; ++index)
|
|
{
|
|
var node = nodes[index];
|
|
|
|
if (node.nodeType === 3 || node.nodeType === 4)
|
|
text += node.nodeValue;
|
|
|
|
else if (node.nodeType !== 8)
|
|
text += textContent(node.childNodes);
|
|
}
|
|
|
|
return text;
|
|
}
|
|
|
|
var _plist_traverseNextNode = function(anXMLNode, stayWithin, stack)
|
|
{
|
|
var node = anXMLNode;
|
|
|
|
PLIST_FIRST_CHILD(node);
|
|
|
|
// If this element has a child, traverse to it.
|
|
if (node)
|
|
return node;
|
|
|
|
// If not, first check if it is a container class (as opposed to a designated leaf).
|
|
// If it is, then we have to pop this container off the stack, since it is empty.
|
|
if (NODE_NAME(anXMLNode) === PLIST_ARRAY || NODE_NAME(anXMLNode) === PLIST_DICTIONARY)
|
|
stack.pop();
|
|
|
|
// If not, next check whether it has a sibling.
|
|
else
|
|
{
|
|
if (node === stayWithin)
|
|
return NULL;
|
|
|
|
node = anXMLNode;
|
|
|
|
PLIST_NEXT_SIBLING(node);
|
|
|
|
if (node)
|
|
return node;
|
|
}
|
|
|
|
// If it doesn't, start working our way back up the node tree.
|
|
node = anXMLNode;
|
|
|
|
// While we have a node and it doesn't have a sibling (and we're within our stayWithin),
|
|
// keep moving up.
|
|
while (node)
|
|
{
|
|
var next = node;
|
|
|
|
PLIST_NEXT_SIBLING(next);
|
|
|
|
// If we have a next sibling, just go to it.
|
|
if (next)
|
|
return next;
|
|
|
|
var node = PARENT_NODE(node);
|
|
|
|
// If we are being asked to move up, and our parent is the stay within, then just
|
|
if (stayWithin && node === stayWithin)
|
|
return NULL;
|
|
|
|
// Pop the stack if we have officially "moved up"
|
|
stack.pop();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
CFPropertyList.propertyListFromData = function(/*Data*/ aData, /*Format*/ aFormat)
|
|
{
|
|
return CFPropertyList.propertyListFromString(aData.rawString(), aFormat);
|
|
}
|
|
|
|
CFPropertyList.propertyListFromString = function(/*String*/ aString, /*Format*/ aFormat)
|
|
{
|
|
if (!aFormat)
|
|
aFormat = CFPropertyList.sniffedFormatOfString(aString);
|
|
|
|
if (aFormat === CFPropertyList.FormatXML_v1_0)
|
|
return CFPropertyList.propertyListFromXML(aString);
|
|
|
|
if (aFormat === CFPropertyList.Format280North_v1_0)
|
|
return propertyListFrom280NorthString(aString);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// 280 North Plist Format
|
|
|
|
var ARRAY_MARKER = "A",
|
|
DICTIONARY_MARKER = "D",
|
|
FLOAT_MARKER = "f",
|
|
INTEGER_MARKER = "d",
|
|
STRING_MARKER = "S",
|
|
TRUE_MARKER = "T",
|
|
FALSE_MARKER = "F",
|
|
KEY_MARKER = "K",
|
|
END_MARKER = "E";
|
|
|
|
function propertyListFrom280NorthString(/*String*/ aString)
|
|
{
|
|
var stream = new MarkedStream(aString),
|
|
|
|
marker = NULL,
|
|
|
|
key = "",
|
|
object = NULL,
|
|
plistObject = NULL,
|
|
|
|
containers = [],
|
|
currentContainer = NULL;
|
|
|
|
while (marker = stream.getMarker())
|
|
{
|
|
if (marker === END_MARKER)
|
|
{
|
|
containers.pop();
|
|
continue;
|
|
}
|
|
|
|
var count = containers.length;
|
|
|
|
if (count)
|
|
currentContainer = containers[count - 1];
|
|
|
|
if (marker === KEY_MARKER)
|
|
{
|
|
key = stream.getString();
|
|
marker = stream.getMarker();
|
|
}
|
|
|
|
switch (marker)
|
|
{
|
|
case ARRAY_MARKER: object = []
|
|
containers.push(object);
|
|
break;
|
|
case DICTIONARY_MARKER: object = new CFMutableDictionary();
|
|
containers.push(object);
|
|
break;
|
|
|
|
case FLOAT_MARKER: object = parseFloat(stream.getString());
|
|
break;
|
|
|
|
case INTEGER_MARKER: object = parseInt(stream.getString(), 10);
|
|
break;
|
|
|
|
case STRING_MARKER: object = stream.getString();
|
|
break;
|
|
|
|
case TRUE_MARKER: object = YES;
|
|
break;
|
|
case FALSE_MARKER: object = NO;
|
|
break;
|
|
|
|
default: throw new Error("*** " + marker + " marker not recognized in Plist.");
|
|
}
|
|
|
|
if (!plistObject)
|
|
plistObject = object;
|
|
|
|
else if (currentContainer)
|
|
// If the container is an array...
|
|
if (currentContainer.slice)
|
|
currentContainer.push(object);
|
|
else
|
|
currentContainer.setValueForKey(key, object);
|
|
}
|
|
|
|
return plistObject;
|
|
}
|
|
|
|
function encodeHTMLComponent(/*String*/ aString)
|
|
{
|
|
return aString.replace(/&/g,'&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g,'<').replace(/>/g,'>');
|
|
}
|
|
|
|
function decodeHTMLComponent(/*String*/ aString)
|
|
{
|
|
return aString.replace(/"/g, '"').replace(/'/g, '\'').replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
|
|
}
|
|
|
|
function parseXML(/*String*/ aString)
|
|
{
|
|
if (window.DOMParser)
|
|
return DOCUMENT_ELEMENT(new window.DOMParser().parseFromString(aString, "text/xml"));
|
|
|
|
else if (window.ActiveXObject)
|
|
{
|
|
XMLNode = new ActiveXObject("Microsoft.XMLDOM");
|
|
|
|
// Extract the DTD, which confuses IE.
|
|
var matches = aString.match(CFPropertyList.DTDRE);
|
|
|
|
if (matches)
|
|
aString = aString.substr(matches[0].length);
|
|
|
|
XMLNode.loadXML(aString);
|
|
|
|
return XMLNode
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
CFPropertyList.propertyListFromXML = function(/*String | XMLNode*/ aStringOrXMLNode)
|
|
{
|
|
var XMLNode = aStringOrXMLNode;
|
|
|
|
if (aStringOrXMLNode.valueOf && typeof aStringOrXMLNode.valueOf() === "string")
|
|
XMLNode = parseXML(aStringOrXMLNode);
|
|
|
|
// Skip over DOCTYPE and so forth.
|
|
while (XMLNode && (IS_OF_TYPE(XMLNode, XML_DOCUMENT) || IS_OF_TYPE(XMLNode, XML_XML))) {
|
|
PLIST_FIRST_CHILD(XMLNode);
|
|
}
|
|
|
|
// Skip over the DOCTYPE... see a pattern?
|
|
if (XMLNode && IS_DOCUMENTTYPE(XMLNode))
|
|
PLIST_NEXT_SIBLING(XMLNode);
|
|
|
|
// If this is not a PLIST, bail.
|
|
if (!XMLNode || !IS_PLIST(XMLNode))
|
|
return NULL;
|
|
|
|
var key = "",
|
|
object = NULL,
|
|
plistObject = NULL,
|
|
|
|
plistNode = XMLNode,
|
|
|
|
containers = [],
|
|
currentContainer = NULL;
|
|
|
|
while (XMLNode = _plist_traverseNextNode(XMLNode, plistNode, containers))
|
|
{
|
|
var count = containers.length;
|
|
|
|
if (count)
|
|
currentContainer = containers[count - 1];
|
|
|
|
if (NODE_NAME(XMLNode) === PLIST_KEY)
|
|
{
|
|
key = TEXT_CONTENT(XMLNode);
|
|
PLIST_NEXT_SIBLING(XMLNode);
|
|
}
|
|
|
|
switch (String(NODE_NAME(XMLNode)))
|
|
{
|
|
case PLIST_ARRAY: object = []
|
|
containers.push(object);
|
|
break;
|
|
case PLIST_DICTIONARY: object = new CFMutableDictionary();
|
|
containers.push(object);
|
|
break;
|
|
|
|
case PLIST_NUMBER_REAL: object = parseFloat(TEXT_CONTENT(XMLNode));
|
|
break;
|
|
case PLIST_NUMBER_INTEGER: object = parseInt(TEXT_CONTENT(XMLNode), 10);
|
|
break;
|
|
|
|
case PLIST_STRING: if (HAS_ATTRIBUTE_VALUE(XMLNode, "type", "base64"))
|
|
object = FIRST_CHILD(XMLNode) ? CFData.decodeBase64ToString(TEXT_CONTENT(XMLNode)) : "";
|
|
else
|
|
object = decodeHTMLComponent(FIRST_CHILD(XMLNode) ? TEXT_CONTENT(XMLNode) : "");
|
|
|
|
break;
|
|
|
|
case PLIST_DATE: var timestamp = Date.parseISO8601(TEXT_CONTENT(XMLNode));
|
|
object = isNaN(timestamp) ? new Date() : new Date(timestamp);
|
|
break;
|
|
|
|
case PLIST_BOOLEAN_TRUE: object = YES;
|
|
break;
|
|
case PLIST_BOOLEAN_FALSE: object = NO;
|
|
break;
|
|
|
|
case PLIST_DATA: object = new CFMutableData();
|
|
var data_bytes = FIRST_CHILD(XMLNode) ? CFData.decodeBase64ToArray(TEXT_CONTENT(XMLNode), YES) : [];
|
|
object.setBytes(data_bytes);
|
|
break;
|
|
|
|
default: throw new Error("*** " + NODE_NAME(XMLNode) + " tag not recognized in Plist.");
|
|
}
|
|
|
|
if (!plistObject)
|
|
plistObject = object;
|
|
|
|
else if (currentContainer)
|
|
// If the container is an array...
|
|
if (currentContainer.slice)
|
|
currentContainer.push(object);
|
|
else
|
|
currentContainer.setValueForKey(key, object);
|
|
}
|
|
|
|
return plistObject;
|
|
}
|
|
|
|
GLOBAL(kCFPropertyListOpenStepFormat) = CFPropertyList.FormatOpenStep;
|
|
GLOBAL(kCFPropertyListXMLFormat_v1_0) = CFPropertyList.FormatXML_v1_0;
|
|
GLOBAL(kCFPropertyListBinaryFormat_v1_0) = CFPropertyList.FormatBinary_v1_0;
|
|
GLOBAL(kCFPropertyList280NorthFormat_v1_0) = CFPropertyList.Format280North_v1_0;
|
|
|
|
GLOBAL(CFPropertyListCreate) = function()
|
|
{
|
|
return new CFPropertyList();
|
|
}
|
|
|
|
GLOBAL(CFPropertyListCreateFromXMLData) = function(/*Data*/ data)
|
|
{
|
|
return CFPropertyList.propertyListFromData(data, CFPropertyList.FormatXML_v1_0);
|
|
}
|
|
|
|
GLOBAL(CFPropertyListCreateXMLData) = function(/*PropertyList*/ aPropertyList)
|
|
{
|
|
return CFPropertyList.dataFromPropertyList(aPropertyList, CFPropertyList.FormatXML_v1_0);
|
|
}
|
|
|
|
GLOBAL(CFPropertyListCreateFrom280NorthData) = function(/*Data*/ data)
|
|
{
|
|
return CFPropertyList.propertyListFromData(data, CFPropertyList.Format280North_v1_0);
|
|
}
|
|
|
|
GLOBAL(CFPropertyListCreate280NorthData) = function(/*PropertyList*/ aPropertyList)
|
|
{
|
|
return CFPropertyList.dataFromPropertyList(aPropertyList, CFPropertyList.Format280North_v1_0);
|
|
}
|
|
|
|
GLOBAL(CPPropertyListCreateFromData) = function(/*CFData*/ data, /*Format*/ aFormat)
|
|
{
|
|
return CFPropertyList.propertyListFromData(data, aFormat);
|
|
}
|
|
|
|
GLOBAL(CPPropertyListCreateData) = function(/*PropertyList*/ aPropertyList, /*Format*/ aFormat)
|
|
{
|
|
return CFPropertyList.dataFromPropertyList(aPropertyList, aFormat);
|
|
};
|