Changes between Initial Version and Version 1 of XeromycesExample


Ignore:
Timestamp:
Feb 14, 2009, 12:02:51 PM (15 years ago)
Author:
Philip Taylor
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • XeromycesExample

    v1 v1  
     1Consider a hypothetical XML-based image format:
     2
     3{{{
     4#!xml
     5<?xml version="1.0" encoding="utf-8"?>
     6<image>
     7<width>2</width>
     8<height>2</height>
     9<row>
     10  <pixel red="255" green="0" blue="255"/>
     11  <pixel red="255" green="0" blue="128"/>
     12</row>
     13<row>
     14  <pixel red="255" green="0" blue="128"/>
     15  <pixel red="255" green="0" blue="0"/>
     16</row>
     17</image>
     18}}}
     19
     20The code to read it would look something like:
     21{{{
     22#!c
     23void ReadImage(const char* Filename)
     24{
     25
     26    // First you need to load an XML file from disk. It uses the VFS system,
     27    // so put all the XML files inside data/mods/official/<Filename>.
     28    // The XML is automatically converted to an XMB when necessary.
     29    // Load() returns either PSRETURN_OK or a PSRETURN_Xeromyces_*
     30
     31    CXeromyces XeroFile;
     32    if (XeroFile.Load(Filename) != PSRETURN_OK)
     33        // Loading failed - respond in whatever way is appropriate.
     34        return;
     35
     36    // Rather than doing a large number of string comparisons, Xeromyces
     37    // gives a unique numeric ID to each element and attribute name in a
     38    // file; the numbers must therefore be read before you can understand
     39    // the file's content.
     40    //
     41    // The element/attribute names *must* be specified here in lowercase.
     42    // (The system is case-sensitive; the XML files are automatically
     43    // converted to lowercase, but strings in the code aren't.)
     44    //
     45    // If an element/attribute doesn't exist in that particular file,
     46    // it will return an ID of -1.
     47
     48    int el_image  = XeroFile.getElementID("image");
     49    int el_width  = XeroFile.getElementID("width");
     50    int el_height = XeroFile.getElementID("height");
     51    int el_row    = XeroFile.getElementID("row");
     52
     53    // All XML files have a single root element (in this example it's
     54    // the <image>). The "XMBElement" class provides access to the
     55    // element.
     56
     57    XMBElement Root = XeroFile.getRoot();
     58
     59    // If you're paranoid, check that you're actually reading the
     60    // correct type of XML file.
     61    assert(Root.getNodeName() == el_image);
     62
     63    // Some uninteresting things to help with the example:
     64    int width, height;
     65    pixel pixels[MAX_IMAGE_SIZE][MAX_IMAGE_SIZE];
     66    int y = 0;
     67
     68    // You now iterate through each child element of the root element -
     69    // in this example, the children are <width>, <height> and two <row>s.
     70
     71    XMBElementList RootChildren = Root.getChildNodes();
     72
     73    for (int i = 0; i < RootChildren.Count; ++i)
     74    {
     75        XMBElement Child = RootChildren.item(i);
     76
     77        // Now you check what type of element it is, and respond appropriately.
     78
     79        int ChildName = Child.getNodeName();
     80
     81        if (ChildName == el_width)
     82        {
     83            CStr val (Child.getText());
     84            width = val.ToInt();
     85        }
     86        // It's possible to use strings rather than the IDs, although
     87        // it isn't particularly efficient.
     88        // getElementString translates an ID back into a string.
     89        else if (XeroFile.getElementString(ChildName) == "height")
     90        {
     91            CStr val (Child.getText());
     92            height = val.ToInt();
     93        }
     94        else if (ChildName == el_row)
     95        {
     96            // Since XML files tend to be recursive, it's generally nicer
     97            // to split things into several functions.
     98            ReadPixelRow(Child, XeroFile, pixels[y++]);
     99        }
     100    }
     101}
     102
     103
     104// XMBElements are only 4 bytes, so there's no need to pass them
     105// around in a more efficient way.
     106void ReadPixelRow(XMBElement Row, CXeromyces& XeroFile, pixel* Pixels)
     107{
     108
     109    // Load the IDs for the elements/attributes that are
     110    // going to be used in this pixel.
     111    int el_pixel = XeroFile.getElementID("pixel");
     112    int at_red   = XeroFile.getAttributeID("red");
     113    int at_green = XeroFile.getAttributeID("green");
     114    int at_blue  = XeroFile.getAttributeID("blue");
     115
     116    // Iterate through the children again
     117    XMBElementList Children = Row.getChildNodes();
     118    for (int x = 0; x < Children.Count; ++x)
     119    {
     120        XMBElement Pixel = Children.item(x);
     121
     122        assert(Pixel.getNodeName() == el_pixel);
     123
     124        // You can iterate through the attributes in the same way:
     125        XMBAttributeList Attrs = Pixel.getAttributes();
     126        for (int i = 0; i < Attrs.Count; ++i)
     127        {
     128            XMBAttribute Attr = Attrs.item(i);
     129
     130            if (Attr.Name == at_red)
     131            {
     132                CStr val (Attr.Value);
     133                Pixels[x].r = val.ToInt();
     134            }
     135            else if (Attr.Name == at_green)
     136            {
     137                CStr val (Attr.Value);
     138                Pixels[x].g = val.ToInt();
     139            }
     140        }
     141
     142        // You can also get attributes by asking for a particular
     143        // one, which is sometimes more convenient.
     144        // getNamedItem() returns an empty string if the attribute
     145        // has not been specified in the file.
     146
     147        CStr val (Attrs.getNamedItem(at_blue));
     148        Pixels[x].b = val.ToInt();
     149    }
     150}
     151}}}