Property list

From Elite Wiki
Revision as of 09:24, 19 May 2023 by Cholmondely (talk | contribs) (Links: Added another)
the plist formats, XML and OpenStep

A property list, or plist for short, is data structured in a standardized way, used by Oolite for a wide variety of configuration files. The concept originates with OpenStep, the specification on which the Cocoa and GNUstep programming libraries Oolite uses are based.

Formats

A property list is an abstract structure which can be represented files using at least five different formats. Since Oolite uses two different implementations of property list support, one on Mac OS X and another on other platforms, it can’t consistently read all these formats.

Two formats are recommended for Oolite: the traditional OpenStep format, which is easy to read, and the XML format, which is more flexible. The other formats are Apple binary format (which can be read by both implementations, but is not human-readable), and the GNUstep text and binary formats, which are not supported under Mac OS X.

While the OpenStep format does not support all the data types used by Oolite – specifically, it does not support integers, reals or booleans – Oolite can in most cases automatically convert strings to these types starting with Oolite 1.69. (If you find an exception, please report it.) As such, the types can be used interchangeably. In prior versions of Oolite, some types, especially booleans, could not be converted automatically, so XML format was required for some property lists.


Data types

The rest of this page describes the types of property list element used by Oolite, and how they are represented in OpenStep and XML format property lists. It does not cover all property list content types or file formats and is not a general-purpose reference to property lists.


string

A string is a block of text. In OpenStep format plists, this is surrounded by straight double quotation marks, with “\” being used to escape quotation marks within the string: "a string with a \"quotation\" and a <tag>". OpenStep format plists also allow single-word strings to be used without quotation marks when this is unambiguous. However, the definition of “unambiguous” differs between Mac OS X and GNUstep, so this usage is not recommended except for numbers. In XML format, it is surrounded by <string> tags, escaping contents with XML entities: <string>a string with a &quot;quotation&quot; and a &lt;tag&gt;</string>.


integer

An integer is a whole number. In OpenStep format plists, an integer is a string whose contents happen to be digits (and optionally a minus sign), and may be unquoted: -12345. In XML format, it is surrounded by <integer> tags: <integer>-12345</integer>.


real

A real is a number with a fractional part. In OpenStep format plists, reals are again written as unquoted strings: 42.123. In XML format, reals are surrounded by <real> tags: <real>42.123</real>. Large reals can be expressed in scientific notation: 1.35e+20 means 1.35 × 1020. Integers and reals are mostly interchangeable in Oolite.


boolean

A boolean is either of the values true or false. In XML format, the tags <true/> and <false/> can be used. OpenStep format does not support booleans. However, as of Oolite 1.69, a number of different methods can be used to represent them: any of the strings "true", "yes" or "on" may be used to represent true, and any of the strings "false", "no" or "off" may be used to represent false. Also the uppercase variants of these keywords can be used as casing is ignored for these booleans. Additionally, the number 0 is interpreted as false and any other number as true (but see fuzzy boolean below). The recommended form is to use "yes" and "no" to keep a consistent syntax that is not confusing.

Previous versions of this page indicated that numbers could be used as booleans in OpenStep-format property lists in any version of Oolite. This is incorrect and such usage will not work with versions prior to 1.69.

fuzzy boolean

A fuzzy boolean isn't really a property list type; rather, it's a special usage defined by Oolite. If a fuzzy boolean is expected, and a number is encountered, it is treated as a probability between 0 and 1. For instance, if a value of 0.5 is used, it will be treated as true half the time, and false the other half. Values other than numbers are treated like booleans.


array

An array is an ordered list of objects.

In OpenStep format, an array is contained in parentheses, with items separated by commas: (0, two, "three and a half", yes). You can have several values without name, and they are grouped using round brackets:

(
value1,
value2,
value3
)

Note that between two values there is a comma.


In XML format, it is contained in <array> tags: <array><integer>0</integer> <string>two</string> <string>three and a half</string> <true/></array>.

Later the values are just accessed by numbers: The first, the second, the next, the last, ...

Now the part that can make plist files really complex: Wherever you place a value, it can be a primitive one (a number, a string, a boolean value like true/false) or a complex value such as an array or a dictionary. And with this you can create all the complex structures you perceive when looking at Oolite's plist files.

dictionary

Dictionaries are the most complex type. They consist of key/value pairs – each pair consists of a key, which is always a string, and a value, which can be any type, including other dictionaries. Each key must be unique, and the order of pairs is not significant. Again, every value has a name or a key.

In OpenStep format, dictionaries are contained in braces, with key and value separated by = signs and each pair followed by a semicolon:

{
  "name1" = "value1";
  "name2" = "value2";
}

Not all names have to go into quotes, and not all values require them. But you need to watch out where you place them and where not.

{
  length = 42;
  width = 36.5;
  "long name" = "this is a thing with a really quite long name"; // note: quotes for a key with spaces are required
  attributes = ("hairy", "muscular"); // note: this is actually an array of string values following the key
}


In XML format, dictionaries are contained in <dict> tags,
with keys specified by <key> tags
and immediately followed by values with whatever tag is appropriate for the value type:

<dict>
  <key>length</key>
  <integer>42</integer> 
  <key>width</key>
  <real>36.5</real>
  <key>long name</key>
  <string>this is a thing with a really quite long name</string>  
  <key>attributes</key>
  <array>
    <string>hairy</string>
    <string>muscular</string>
  </array>  
</dict>

Root element

Every property list has a single value as its root. Typically this is a dictionary. In XML format, the root value must be surrounded by <plist> tags in addition to its normal type tag: <plist> <dictionary> <key>green</key> <array> <integer>0</integer> <integer>1</integer> <integer>0</integer> </array> </dictionary> </plist> (OpenStep equivalent: { green = (0, 1, 0); }).

Under Mac OS X, if the root element of an OpenStep-format property list is a dictionary, it does not have to be surrounded by braces. However, this does not work under GNUstep, so those creating property lists on Macs must be careful. In particular, OpenStep-format property lists exported by Property List Editor may not work under GNUstep.

Comments

Both formats can also contain comments, which are ignored by the program but are useful to human readers. In OpenStep format, these can either start with “//” and continue to the end of the line, or start with “/*” and end with “*/”. In XML, they start with “<!--” and end with “-->” (and must not contain “--” anywhere else in the comment).

Examples:

/* this line is a comment in OpenStep format */
// this line is also a comment in OpenStep format
<!-- this line is a comment in XML -->


XML Preamble

XML plists also need a standard header, which looks like this:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">


Real-world Example

The following is a shortened version of Oolite’s built-in equipment.plist, in both OpenStep and XML formats.

OpenStep

(
    (
        1, 300, "Missile", "EQ_MISSILE",
        "Faulcon de Lacy HM3 homing missile, fast and accurate when used in conjunction with standard targetting scanners.",
        {
            available_to_all = "yes";
        }
    ),
    (
        7, 9000, "Energy Bomb", "EQ_ENERGY_BOMB",
        "A one-shot super-weapon capable of destroying all small craft within range."
    )
)

The round brackets are arrays in OpenStep, and are used to group information for a given key. Examples are the exhaust (if one has multiple ones for a given ship), the individual custom views and sub-entities...

The curly brackets make up dictionaries, which tie together different keys on the same subject. The two main examples there are the overall entries themselves (each ship is made up of a dictionary of keys describing it) and the external views (a dictionary of individual views, each of which is defined as an array of keys describing that given view).

One would recommend using a programmer-friendly editor like notepad++ or an equivalent. On N++ if you select an open or closing bracket (of whichever flavour) it will automatically highlight the other part of the pair and link them. It's useful for quickly checking that you have your pairs correct - a good habit to get into. And in many cases the kind of log error one sees is indicative of missing brackets. Those and missing quotes and semi-colons are arguably the three most common errors in openStep plists if one excludes typo's. Thargoid (2011)

XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <array>
        <integer>1</integer>
        <integer>300</integer>
        <string>Missile</string>
        <string>EQ_MISSILE</string>
        <string>Faulcon de Lacy HM3 homing missile, fast and accurate when used in conjunction with
                standard targetting scanners.</string>
        <dict>
            <key>available_to_all</key>
            <true/>
        </dict>
    </array>
    <array>
        <integer>7</integer>
        <integer>9000</integer>
        <string>Energy Bomb</string>
        <string>EQ_ENERGY_BOMB</string>
        <string>A one-shot super-weapon capable of destroying all small craft within range.</string>
    </array>
</array>
</plist>


Conversion

Technically the XML plists are the best, but they are only fully supported on Mac systems. Without a plist editor, the plists are not as easy to read or write as OpenStep plists. However, those editors are only easily available for the Mac. Windows and Linux users will have to rely on text editors to edit those plists. Therefore it is advised to write everything in open step format.

Converting xml to open step can be done by a python script, written by Cdr. Jettison: download python conversion script ( xml plist must be free of comment for the script to work)

Note that this conversion script contains CR/LF (carriage return/linefeed) end-of-lines, as used on Windows computers. This will cause "bad interpreter: No such file or directory" errors if run on Linux. You can strip out the CR characters yourself, or download this copy of the script which has already had the CRs removed. (you will also need to make the script executable)

Links