diff --git a/source/dom_persist.d b/source/dom_persist.d index ead40bf..bcb8b2c 100644 --- a/source/dom_persist.d +++ b/source/dom_persist.d @@ -12,20 +12,32 @@ import nodecode; -import d2sqlite3; // https://d2sqlite3.dpldocs.info/v1.0.0/d2sqlite3.database.Database.this.html - // https://dlang-community.github.io/d2sqlite3/d2sqlite3.html +// https://d2sqlite3.dpldocs.info/v1.0.0/d2sqlite3.database.Database.this.html +// https://d2sqlite3.dpldocs.info/v1.0.0/source/tests.d.d.html +// https://dlang-community.github.io/d2sqlite3/d2sqlite3.html +// https://code.dlang.org/packages/d2sqlite3 +import d2sqlite3; +/** + * Return true if the database exists. + */ bool db_exists( string sqlite_filename ){ return sqlite_filename.exists; } +/** + * Drop the database and remove the DB file + */ void db_drop( string sqlite_filename ){ if( sqlite_filename.exists ){ sqlite_filename.remove(); } } +/** + * Create the database file and the params table with the DB version number. + */ Database db_create( string sqlite_filename, int db_ver ){ auto db = Database( sqlite_filename ); @@ -35,82 +47,19 @@ } -string get_openTag_commence( TreeNodeType nt, string e_data ){ - - switch( nt ){ - - case TreeNodeType.text: - return e_data; - - case TreeNodeType.comment: - return ""; - - default: - switch(e_data){ - case "input": - case "br": - return ""; - default: - } - - return format("", e_data); - } - -} struct TreeNameID { long tree_id; string name; } - /** * An instance of this class contains access to a single tree. Tree operations are cached in RAM and only written to - * disk during a save operation. This can be done safely because of the single user access to Sqlite. + * disk when flush is called. This can be done safely because of the single user access to Sqlite. * - * Multiple database connections should work on the same thread provided each is using a different tree. + * Multiple database connections have not been tested. + * Multiple threads not yet supported. * - * Instantiation of the tree involves only one database select. */ class Tree_Db { @@ -176,6 +125,9 @@ public: + /** + * Create the Database schema for the trees. + */ static void db_create_schema( ref Database db ){ db.run("CREATE TABLE IF NOT EXISTS doctree (ID INTEGER, e_data TEXT,p_id INTEGER,t_id INTEGER NOT NULL,tree_id INTEGER NOT NULL, c_order INTEGER, PRIMARY KEY( ID AUTOINCREMENT))"); } @@ -205,7 +157,7 @@ } /** - * Load a tree into RAM from database given the tree ID. + * Load a tree into RAM from database given the tree ID. Reads the complete tree and involves only one database select. */ static Tree_Db loadTree( ref Database db, long tree_id ){ return new Tree_Db( &db, tree_id ); @@ -437,6 +389,68 @@ } +private string get_openTag_commence( TreeNodeType nt, string e_data ){ + + switch( nt ){ + + case TreeNodeType.text: + return e_data; + + case TreeNodeType.comment: + return ""; + + default: + switch(e_data){ + case "input": + case "br": + return ""; + default: + } + + return format("", e_data); + } + +} /** * Iterator starting at any given TreeNode, traversing each of the descendent nodes, depth first and increasing child index. diff --git a/source/nodecode.d b/source/nodecode.d index 022cdb1..422b2f1 100644 --- a/source/nodecode.d +++ b/source/nodecode.d @@ -20,15 +20,16 @@ return TreeNodeType.nulltype; } - +/** + * Node data held by each TreeNode. + */ struct NodeData { - long ID; - string e_data; - long pid; + long ID; // The (database) ID of this node. negative IDs are new nodes not yet flushed + string e_data; // Data specific to the node. e.g. element name, or comment text etc.. + long pid; // Parent node ID. If not connected then zero TreeNodeType type; - bool dirty = false; - long orig_pid=0; + bool dirty = false; // true when any node data changes indicating a DB write is required. this( long ID, string e_data, long pid, TreeNodeType type){ this.ID = ID; @@ -39,14 +40,9 @@ } /** - * TreeNode is a class because we need the references to remain valid when we modify containers such as - * the hashmap which indexes on ID. + * Each element in the tree is represented by an instance of TreeNode. * - * If we use a struct, then we need to hold the TreeNode data somewhere in order to use a pointer to the data. If - * we move the data, such as updating a map, then all the pointers need to change, or we need pointers to pointers. - * Either is not ideal. If we use references, as provided by a class, then the GC will track the references and ensure - * that they remain valid. We can move the references knowing that the data remains in place on the heap - * + * This class contains node specific operations such as reading, mutation, relocation etc.. */ class TreeNode { @@ -155,14 +151,16 @@ } /** - * Delete this node from the the tree. + * Delete this node and all it's descendents from the the tree. */ void deleteNode( ){ owner_tree.deleteNode( this ); } /** - * Internal use only + * Internal use only. + * + * Locate the child node (c_node) and snip it off. */ void cutChild( TreeNode c_node ){ foreach( i, child; child_nodes ){