I recently committed my LLSD parser to the public SVN server, after someone posted on the RegAPI mailing list asking for a LLSD parser that worked under PHP5.First the example script, then a step by step explanation of the output.
01 <?php02 header('Content-Type:text/plain'); # makes it easier to read the output03 define('UHU_DEBUG_MODE',true); # enables extended error reporting04 define('UHU_ERROR_AS_EXCEPTION',true); #05 define('UHU_ROOT','s:/uhu public SVN/trunk/uhu-5'); # change to the directory06 define('UHU_CONFIG_PATH','s:/uhu public SVN/trunk/uhu-5/uhu-config.php'); # change the path also07 define('UHU_LIBS','s:/uhu public SVN/trunk/uhu-5/libs'); # ditto08 require_once(UHU_ROOT . '/uhu.php'); # no need to change this09 uhu::load_apps(); # an empty call needs to be made if the install root is not declared inside the config or if it needs to be overriden.10 uhu_install_config::set('uhu::install::site_root','s:\localhost',true); # change to the path of the root directory for the install- not the web root, as some UHU components like to use a cache directory etc.11 uhu::load_components('LLSD'); # loads the LLSD parser12 $source = file_get_contents('./sample.llsd'); # go nab http://wiki.secondlife.com/wiki/LLSD#Example_XML_Output13 $LLSD = new uhu_LLSD($source);14 echo15 print_r($LLSD->struct()->struct(),true),"\n\n", # yeah, I should probably refactor this double geekery out.16 uhu_LLSD::save($LLSD->struct(),0),"\n\n",17 uhu_LLSD::save(NULL_KEY,0),"\n\n",18 uhu_LLSD::save(new uhu_LLSD_UUID(NULL_KEY),0),"\n\n",19 uhu_LLSD::save(new uhu_LLSD_integer_NaN,0)20 ;21 ?>
As noted in the PHP example, I do need to refactor out the double function thing to get the pure native PHP version of an LLSD script, but as you can see, the map from the example LLSD document has been converted into an associative array. The default return format supports the Iterator interface, so if you’re just wanting to loop over an array, you don’t need to get the pure PHP data type of the LLSD document.
01 Array02 (03 [region_id] => uhu_LLSD_UUID Object04 (05 [uuid:protected] => 67153d5b-3659-afb4-8510-adda2c03464906 )07 08 [scale] => one minute09 [simulator statistics] => Array10 (11 [time dilation] => 0.987862412 [sim fps] => 44.3889813 [pysics fps] => 44.3890614 [agent updates per second] => uhu_LLSD_real_NaN Object15 (16 )17 18 [lsl instructions per second] => 019 [total task count] => 420 [active task count] => 021 [active script count] => 422 [main agent count] => 023 [child agent count] => 024 [inbound packets per second] => 1.22828325 [outbound packets per second] => 1.27750826 [pending downloads] => 027 [pending uploads] => 0.000109652528 [frame ms] => 0.775788629 [net ms] => 0.315291930 [sim other ms] => 0.182693731 [sim physics ms] => 0.0432305532 [agent ms] => 0.0159902933 [image ms] => 0.0186595534 [script ms] => 0.133883635 )36 37 )38
The output of uhu_LLSD::save($LLSD->struct(),0) removed for brevity- expect the output to be near-identical to the original source, except with minor optimisations.
Lines 17 and 18 of the example script demonstrate the difference between passing a UUID as a string and as a UUID object. Strings are just strings, so a UUID in an LLSD document is no different than any other string, as far as the parser is concerned. However, when a UUID is detected, the parser will use a special object to house the UUID- this is so when it is saved back to LLSD, it can use the correct encapsulating element. Also note, that in accordance with the LLSD spec, “empty” values can be represented as closed tags- so rather than doing <uuid>00000000-0000-0000-0000-000000000000</uuid>, the parser will do <uuid />- saving a teensy bit of storage/bandwidth in the process.
1 2 <llsd>3 <string>00000000-0000-0000-0000-000000000000</string>4 </llsd>5 6 <llsd>7 <uuid />8 </llsd>9
Line 19 just serves as a quick demonstration on how to do include a NaN if you wanted to build an LLSD document from scratch with uhu_LLSD::save().
1 2 <llsd>3 <integer>nan</integer>4 </llsd>
The public SVN is over at google code, and the documentation is available on my site as well as in the repository itself.
