| JezUK Ltd - The Coffee Grounds - December 2005 |
| << November 2005 | January 2006 >> |
Item: Got an inner tube for Christmas. Rock!
Item: Our boiler broke down. Discovered new fangled boilers don't have pilot lights. The pilot light in a boiler served two purposes. The first, obviously, was to light the gas. The second, slightly less obviously, was to keep the gas on. There's a thermocouple mounted in the flame, which controls the gas supply. If the light goes out, the thermocouple cools and the gas is shut off. You turn the tap on, the water stays cold, you go and relight the pilot, everything starts working. Modern boilers are more, well modern. When you turn on the tap, an impellor at the top of the boiler starts up, drawing air through the combustion chamber and also expelling the waste up the flue. Once the fan is turning, a spark generator starts going. Once that's sparking, the gas comes on a bit. Once a flame detector is triggered, the spark genny is turned off and the gas comes full on. It lights. Woo! Then you get your hot water. If any one of those pieces is missing, the water stays cold as do your radiators, so you break out the extra blankets.
Item: We all have a touch of cabin fever.
Item: Dr Who. Bloody marvellous.
Item: Our plumber Dennis is the world's friendliest tradeschap. He couldn't come out because he was childwrangling but, in the manner of me talking my father-in-law through some software exercise only successful, talked me through identifying the fault. It was the fan. The bearing had gone, presumably as a delayed result of the tornado forcing bits of slate back through it.
Item: Lego Loco may be the best game evar!
Item: Daddy fix it! After a couple of hours medical delay (see next item), secured a replacement unit in the wilds of Nechells.
Item: Some old fucker's dog bit me
Item: When you normally only buy the Saturday papers, weekday newspapers seem rather thin.
Item: Natalie's developed a bit of thing for Sudoku.
Item: I reckon I've just experienced the last time I can churn / re-evaluate my 18 month old's toy inventory sans his input. Next year there'll be a fight... [added 30th Dec 2005]
maybe the rogue txt'er is the same gay chap "Peter" from Leith who thinks I share a mobile with his partner "Danny".
[added 26th Dec 2005]
BTW how cn u txt a lndlne? mayb twas Santa. [added 27th Dec 2005]
When it's an XSLT pattern, that's when.
As an XPath
para[@ref]
selects, for a given node, its child para elements which have ref attributes. As an XSLT pattern it tests whether a given node is a para element which has a ref attribute.
Similarly, something like
chapter/para
tests whether a given node is a para element with a chapter element parent. In XPath terms, you'd express it as something like boolean(self::para[parent::chapter]).
Aside from this sematic difference, syntactically XSLT patterns are an XPath subset. I don't have these things evaluating yet but, thanks to the miracle that is Boost::Spirit, I've extended Arabica::XPath to parse them. Took about half an hour, including writing a pile of test cases and getting them passing. It really is a top piece of work. While it's not hard to find people rambling on about how Python or Lisp or whatever really is the thing for writing little domain specific languages, this kind of thing really shows just how deadly cool template metaprogramming can be. Read the EBNF, transcribe it into code, compile, and go. Easy, expressive and type-safe. What more could you want?
I'm sure that quote is attributed to Dan Veillard.
You can see where this is going, can't you.
Damn.
One obvious memory optimisation for DOM trees is string pooling. In any reasonable XML document, there will be a lot of repeated element and attribute names. Rather than every Element node in your tree having its own copy of that name (and quite possibly a namespace URI too), you keep all the names in a common table with the nodes can then point into.
When I first wrote Arabica's DOM I didn't bother, mainly because I more concerned with the memory management aspects of the tree itself, and making it sure it got cleaned up properly. After that, I still didn't bother with it because on the kind of small documents I was working with memory wasn't an issue, and there was always something more exciting to do.
Anyway, I finally implemented string pooling for Element and Attributes names and namespace URIs this morning. It's taken less than two hours. I am a twit.
template<class string_type,
class string_adaptor =
Arabica::default_string_adaptor<string_type> >
class XMLReader : public DEF_SAX_P<string_type, string_adaptor>
{
...
};
and here's another bit
template<class string_type,
class COMInitializer_type = COMSingleThreadInitializer,
class string_adaptor_type =
Arabica::default_string_adaptor<string_type> >
class msxml2_wrapper : public SAX::basic_XMLReader<string_type>
{
...
};
DEF_SAX_P is a macro which expands to the default SAX class name, quite possibly msxml2_wrapper. See the problem? I've built myself a situation where not only does msxml2_wrapper have a different number of parameters than the my other wrappers, the order of the parameters is different too. What a twit. I can't recall the full history (or I'd probably have avoided it) but there's a good reason for msxml2_wrapper's extra parameter, the extra parameter being in an odd place, and for the DEF_SAX_P macro.
So there's the problem. A few years ago, I'd have considered this largely intractable without breaking existing code. Now though, this is a simple meta-programming issue -
struct nil_t { };
template <typename BaseT,
typename DefaultT,
typename T0,
typename T1>
struct get_param
{
typedef typename boost::mpl::if_<
boost::is_base_and_derived<BaseT, T0>
, T0
, typename boost::mpl::if_<
boost::is_base_and_derived<BaseT, T1>
, T1
, DefaultT
>::type
>::type type;
};
template<class string_type,
class T0 = nil_t,
class T1 = nil_t>
class msxml2_wrapper : public SAX::basic_XMLReader<string_type>
{
typedef typename get_param<COMInitializer_tag,
COMSingleThreadInitializer,
T0,
T1>::type COMInitializer_type;
typedef typename get_param<Arabica::string_adaptor_tag,
Arabica::default_string_adaptor<string_type>,
T0,
T1>::type string_adaptor_type;
...
};
This lets us specify the initialiser and string_adaptor parameters in either order. Consequently, the XMLReader definition can be extended to take a third parameter. For people who need pass extra parameters to MSXML, they can. Everyone else can ignore it. Nice.
I made your recipe last week. Two (didn't have a bowl big enough) Xmas puddings are sitting in the cupboard ready for Xmas. One of them is in a see-through Pirex bowl and looks lovely. Yay! [added 14th Dec 2005]
However, on reheating a slice later on it turned into something resembling very tasty muesli. Any tips on reheating? [added 26th Dec 2005]
| << November 2005 | January 2006 >> |