Writing a MODULE_PARSER
 
    How to write a MODULE_PARSER ?
Name

How to write a MODULE_PARSER defining a container.

Versions

Caudium 1.0, 1.2, 1.3

Synopsis

The attached module allows you to define your own RXML Container. This module allows you to parse the contents of a container and calculate values based on the contents. This particular module converts to and from the currency in the popular Harry Potter Series of books.

Documentation

Sometimes it is helpful to create a tag to perform a specific function where it might need to interface with a database, do some mathematical calculation or other function that cannot easily be done in RXML.

This sample module has two containers that are defined. A simple container named <usdtohp> takes the contents and converts USD to Harry Potter Currency.

The second container is a bit more complex and uses containers nested within the container <hptousd>. It takes the arguments <galleons>, <sickles> and <knuts> within the container and converts the result to USD.

In addition, a global variable is used to demonstrate the use of the Status and Debug Info section of the Config Interface. Each time the tag is called, it will increment the counter unless the module is reloaded from the Config Interface.

To use the module, do:

   11.23 USD = <usdtohp>11.23</usdtohp>
   <hptousd>
    <galleons>2</galleons>
    <sickles>5</sickles>
    <knuts>14</knuts>
   </hptousd> USD
   

Notes regarding writing modules:

In your module documentation, you can hardcode a \n in your documentation which will control where the Configuration Interface 'breaks' documentation for the Less Documentation/More Documentation control.

In a container or tag, you must return some value or else Caudium will ignore the results of the tag/container you have written.

Source
#include <module.h>
inherit "module";
inherit "caudiumlib";

// Module Parser, allows definition of tags, etc.
constant module_type = MODULE_PARSER;
constant module_name = "Harry Potter Container Module";
// Note the first \n is where the CIF decides where to wrap for 
// Less Documentation/More Documentation
constant module_doc  = #"This module was designed to show how a container module works.<p>\n
                        Usage:<p>
11.23 USD =<br>
&lt;usdtohp>11.23&lt;/usdtohp><br>
&lt;p><br>
2 Galleons, 5 Sickle, and 14 Knuts = <br>
&lt;hptousd><br>
&lt;galleons>2&lt;/galleons><br>
&lt;sickles>5&lt;/sickles><br>
&lt;knuts>14&lt;/knuts><br>
&lt;/hptousd> USD<br>
<p>\n";
constant module_unique = 1;
constant thread_safe=1;

// Initialize two counters just so we can keep track of how many 
// firstyears are reloading the pages
int	hptousdcount = 0;
int	usdtohpcount = 0;

string container_usdtohp(string t, mapping m, string contents, object id)
{
  usdtohpcount++;

// How do we know this?
// Price of book, $3.99 (14 sickles, 3 knuts)
// 29 knuts in a sickle, 17 sickles in a galleon

int knutindollar = 15 + 3*29;
int knutsinsickle = 29;
int knutsingalleon = 17 * knutsinsickle;

float dollars = (float)contents;
int totalknuts = (int)(dollars*knutindollar+0.5);

int galleons = totalknuts / knutsingalleon;
int sickles = (totalknuts - (galleons * knutsingalleon)) / knutsinsickle;
int knuts = totalknuts - (galleons * knutsingalleon) - (sickles * knutsinsickle);

return(sprintf("%d galleons, %d sickles and %d knuts",galleons,sickles,knuts));

}

string container_hptousd(string t, mapping m, string contents, object id)
{
  hptousdcount++;

// How do we know this?
// Price of book, $3.99 (14 sickles, 3 knuts)
// 29 knuts in a sickle, 17 sickles in a galleon
float knutindollar = (float)(15 + 3*29);
int knutsinsickle = 29;
int knutsingalleon = 17 * knutsinsickle;

// Parse the contents of the container to set id->misc with the appropriate 
// values
string parsed = parse_rxml(contents, id);
int galleons = (int)id->misc->galleons;
int sickles = (int)id->misc->sickles;
int knuts = (int)id->misc->knuts;
float dollars = 0.0;

int totalknuts = (galleons * knutsingalleon) + (sickles * knutsinsickle) + knuts;

return(sprintf("%.2f",totalknuts/knutindollar));

}

// We define a container that is called by 3 different containers in the 
// html.  Since we can see the tag name that was called, we can save time
// and have the same routine called for each tag rather than writing 
// 3 different functions


string container_hpmoney(string tag, mapping m, string contents, object id)
{
// we store the value of the contents in the container in id->misc
  id->misc[tag] = (int)contents;
// Note: Evidently you must have a non-zero return or Caudium ignores 
// the callback
  return("");
}

mapping query_container_callers()
{
  return ([ "usdtohp":container_usdtohp,"hptousd":container_hptousd,
            "galleons":container_hpmoney,"sickles":container_hpmoney,
            "knuts":container_hpmoney
         ]);
}

string status()
{
// This is displayed in the Config Interface, Status
  return("The USDtoHP tag was called "+(string)usdtohpcount+" time(s)<br>"
         "The HPtoUSD tag was called "+(string)hptousdcount+" time(s)<br>");
}

   
Download the source
Get the Module

The module is also available in the Caudium Distribution as Harry Potter Container Module

 
HTML OK CSS