QMLON - An object tree initializer for C++11


bzar

A Commando
Joined
Sep 22, 2008
Messages
4,500
Location
Finland
Website
Visit site
QMLON on github


I started working on a sprite sheet description file format a couple of days back for a project I'm working on. It got a bit out of hand and now I've created a generic object (or struct or anything) tree initializer system that relies heavily on the new C++ standard, C++11. I'm pretty excited about it since it seems to work so well, but I'm sure there are some problems I haven't thought of or improvements that could be done.


This is why I decided to request for comments here. Keep in mind when suggesting that

  • for implementation reasons this is and will be for C++11 (not C, not C++03)
  • generic use is critical
  • qmlon should not impose any requirements for the initialized content other than being able to set initialized properties after construction (if someone has a good idea on how to add generic support for constructor-based initialization I'm all ears)


A short description on how QMLON (stands for QML object notation, since the description files are written in QML-inspired notation) works:


First you create a QMLON-file, which describes the entities you want to initialize. QMLON is kinda like JSON, but has explicitly defined types for objects. For an example of a QMLON file, see spritesheet.qmlon in the (currently only) QMLON spritesheet test.


Second you create initializers for your types, that can set properties and add children to your target data structures. An initializer is a collection of function objects (in most cases created as lambda functions) that are executed based on the QMLON file. Property initializer functions usually are either simple setters that transform the qmlon::Value to a primitive type and set it to the target object, like setting the property "x" here, or compound initializers, like setting property "position" here, that initialize non-trivial structures and generally resemble child object initializer functions, like adding a sprite to a sprite sheet here.


Third you parse your QMLON description from a file or a string using qmlon::readValue. This creates a tree of qmlon::Values and qmlon::Objects that will be used in the initialization.


Fourth you tell qmlon to make you a tree.


And then you're done. Most work goes to writing the initializers, but in my opinion, it's pretty minimal work given the task.


So... comments? :)
 
Last edited by a moderator:
Looks neat! If this was available two months ago, I would probably have used it in my "Microbes" game. Maybe I still will at some point, but at the moment, I don't feel like reimplementing things...
 
some really nice written piece of code. did not have time to get into all those c++11 features, but lambda expressions and the foreach stuff really look nice to use :)
 
Thank-you, citizen. I'll build it and learn some C++11.


Your code has been Judged "pretty good".
 
Last edited by a moderator:
Added validation support. QMLON documents can now be validated using validation documents, which are of course written in qmlon. An example about using the validation system is in test/schema.cpp.


The example first loads a schema that can validate schema documents, then uses it to validate itself. Then it loads a schema document that can validate sprite sheet documents and validates it using the schema validation schema. Finally it loads the sprite sheet from the other example and validates it using the sprite sheet schema.


Try making errors to the documents and report back if things validate when they shouldn't :)
 
Last edited by a moderator:
Just pushed a new format for schemas (validation documents). This one's quite a bit cleaner than the first one.
 
I've updated QMLON again, this time adding some template magic: a generic property setter generator for initializers. Previously you created even simple property mappings like this:



Code:
qmlon::Initializer<FooType> initFoo({

{"bar", [](FooType& foo, qmlon::Value::Reference value) { foo.bar = value->asString(); }}

});



All that boilerplate stuff made me sad, so I added qmlon::set:





Code:
qmlon::Initializer<FooType> initFoo({

{"bar", qmlon::set(&FooType::bar)}

});


qmlon::set works for any boolean, integer, float or string type property and can take a member pointer OR a member function pointer as a parameter. Everything is still nice and independent of the objects you initialize with QMLON. Check the updated sprite sheet example to see it in action.


I'll be adding a similar system for other common operations such as child object creation.


EDIT: and they're there. qmlon::createSet and qmlon::createAdd.
 
Last edited by a moderator:
Back
Top