#include #include #include "stf.hpp" using namespace std; using stfu::node; /*! \author Nick Overdijk * \version 1.2 * \date 2009-04-27 * * STFU Example App */ void prettyprint(const string &title) { cout << "\t\t-----" << title << "-----\t\t\n" << endl; } void read_examples(node &n) { prettyprint("Reading Examples"); cout << "Reading a STF file in a node is trivial with the stream insertion operator, it returns whether it had success: true/false\n" << endl; if ("test.stf" >> n) { prettyprint("Outputting a node/tree"); cout << n; cout << "\n\nnode::getChild() returns a node&, so we can easily output nested nodes:\n" << endl; cout << n.getChild("child"); cout << "\n\nnode::getValue() returns a string&, so we can easily output values too:\n" << endl; cout << n.getValue("imthefirst"); cout << "\n\nThe constness of getChild and getValue depend on the object." << endl; } else { cerr << "Couldn't read file!" << endl; } } void change_examples(node &n) { cout << "\t\t-----Change examples------\t\t\n" << endl; if ("test.stf" >> n) { prettyprint("Edit a value"); cout << "Before:" << endl; cout << n; n.value("imthefirst") = "O YEAH!"; cout << "After: " << endl; cout << n; prettyprint("Edit a node"); cout << "Before:" << endl; cout << n; n.child("child") = n; cout << "After: " << endl; cout << n; prettyprint("Edit the name of a value"); cout << "Before:" << endl; cout << n; n.renameValue("imthefirst", "roflolmao"); cout << "After: " << endl; cout << n; prettyprint("Edit the name of a child"); cout << "Before:" << endl; cout << n; n.renameChild("child", "NEW NAMEZ"); cout << "After: " << endl; cout << n; } else { cerr << "Couldn't read file!" << endl; } } void create_examples(node &n) { prettyprint("Creation examples"); node screenoptions; node soundoptions; if (!("screenoptions.stf" >> screenoptions && "soundoptions.stf" >> soundoptions)) { cerr << "Couldn't read files!" << endl; return; } cout << "You can merge these two tree quite easily into one tree (aka \"Adding children\"):" << endl; cout << "Before (screenoptions):" << endl; cout << screenoptions << endl; cout << "Before (soundoptions):" << endl; cout << soundoptions << endl; //child() creates the child when it doesn't exist n.child("Screen options") = screenoptions; //but you can do this too n.addChild("Sound options", soundoptions); cout << "After (both are now children of options):" << endl; cout << n; prettyprint("Adding a value"); cout << "Before:" << endl; cout << n; //this way, NOT sure child() won't create a child (if it doesn't exist, it'll create it) //also not sure value() won't alter a value (if the value[index] exists, it'll change that) n.child("Screen options").value("Contrast") = "70.1"; //this way, 100% sure that getChild() won't create a child, and addValue() will always add a value //get{Child|Value} throw an out_of_range when they can't find the {Child|Value}. n.getChild("Screen options").addValue("Brightness") = "1.5"; cout << "After:" << endl; cout << n; prettyprint("Writing to a file (aka \"Saving to a file\")"); const char *filename = "ExampleProgramOutput.stf"; if (!(filename << n)) { cerr << "Couldn't write to "; } else { cout << "Node succesfully saved to "; } cout << filename << endl << endl; } void remove_examples(node &n) { prettyprint("Removal examples"); if (!("test.stf" >> n)) { cerr << "Couldn't open file!" << endl; } prettyprint("Deleting a value"); cout << "Before:" << endl; cout << n; //remove{Child|Value} throws an out_of_range when the child/value isn't found n.removeValue("imthefirst"); cout << "After:" << endl; cout << n; prettyprint("Deleting a child/node"); cout << "Before:" << endl; cout << n; n.removeChild("child"); cout << "After:" << endl; cout << n; } void array_examples(node &n) { prettyprint("Array Examples"); if (!("arrays.stf" >> n)) { cerr << "Couldn't open arrays.stf!" << endl; return; } prettyprint("Iterating over an array: try/catch method"); node &array = n.getChild("array"); try { size_t i = 0; while (true) { //use getValue(), it throws an out_of_range when there are no more elements cout << array.getValue(i) << endl; i++; } } catch (out_of_range &e) {/*we're done! ;-)*/} prettyprint("Iterating over an array: size() method"); size_t max = array.values.size(); for(size_t i = 0; i < max; i++){ cout << array.getValue(i) << endl; } prettyprint("Iterating over a 2D-array: size() method"); node &multiarray = n.getChild("2D array"); //rows are children size_t rows = multiarray.children.size(); //each row can have a different amount of cols size_t cols[rows]; for(size_t i = 0; i < rows; i++){ //same as with size() method above cols[i] = multiarray.getChild(i).values.size(); //output to see it for yourself cout << i << ',' << cols[i] << endl; } //so, we're done. Code could've been written in 100 ways, but this does it step by step to be clear. for(size_t row = 0; row < rows; row++){ for(size_t col = 0; col < cols[row]; col++){ cout << multiarray.getChild(row).getValue(col) << ", "; } cout << "\b\b " << endl; } /*Arrays are simply unnamed nodes/values. Nothing more, nothing less. You can change them like nodes/values, add them the same way, etc. Most of the functions are overloaded so that you don't have to specify a name These functions call their overloaded brethren with name = "" */ prettyprint("Creating an array"); cout << "Before:\n\n"; cout << n << endl; node &newarray = n.addChild("my new array"); stringstream buf; for(size_t i = 0; i < 10; i++){ buf << i; newarray.addValue() = buf.str(); } cout << "After:\n\n"; cout << n << endl; } int main() { prettyprint("Welcome to the stf example app"); ifstream license("LICENSE.txt"); if (license.good()) { string line; while (getline(license, line)) { cout << line << endl; } license.close(); } else { cerr << "Couldn't open/read LICENSE.txt" << endl; exit(-1); } cout << endl; cout << "This application shows how easy it is to use STFU (Simple Tree File Utility).\n" << "STF is a \"new\" way to store leveled data, just as XML can do, for example.\n" << "The format looks like a C(++) struct, which we think is easier to read than XML.\n" << "Each {...} is a node, a node has other nodes and values. The file itself is the\n" << "(unnamed) root node.\n" << endl; //create an empty node node n; read_examples(n); n.clear(); change_examples(n); n.clear(); create_examples(n); n.clear(); remove_examples(n); n.clear(); array_examples(n); n.clear(); return 0; }