PLEASE NOTE: PLEASE CONSULT THE PAGE ABOUT THE NEW CACHE IN ADDITION TO THIS PAGE. The major change with this revision is that there is now a cache used for all looped DataValueNodes, but due to the fact that C++ has no garbage collection, the caller of this library must tell the library when it is done using the DataValueNode pointers that may have been cached.
Substantial changes were made in this release of the star library. Because of these changes, some minor alterations to the user code that calls this library will be needed. We tried avoiding this where we could, but in some cases it was inevitable that the changes to the library would end up exposing changes to the users of the library. We have our own code that relies on this library, so rest assured that we are aware of the hassle that a change to the interface creates. We would not have done these changes if we did not deem them necessary.
// old code was: // ofstream *os; // in the global variable section. // ... // os = new ofstream(filedes(stdout)); // ... // NEW CODE: ostream *os; // in the global variable section. ... os = &cout;Also, in the past the os pointer was deleted at the end of most programs. In the case where os is now being initialized by pointing it at cout (as in the example above), it should never be deleted. Instead it should merely be flushed with os->flush(). Deleting (and thus closing) the standard output yields unpredictable results.
LoopTableNode *table = ... ; ... table->erase( &((*table)[N]) );This no longer compiles, because it depended upon the ability to pass a pointer to the object at (*table)[4] to a routine that wanted an iterator on table. Behind the scenes this was because the table object was implemented as an array where a pointer is the only thing one needs to know to find out where one is in the array. You can replace any array subscript notion code as in the following example:
LoopTableNode *table = ... ; ... table->erase( table->begin() + N ); //where N = the index into the tableThis uses iterator arithmetic to achieve the same effect as an array subscript, but does it with iterators instead of pointers.
Essentially, this technique ends up scanning the list of nodes sequentially to find the right iterator that goes with the pointer passed in.
This workaround is as follows:
// (someNode is either a LoopTableNode, or a LoopRowNode, or a // LoopNameListNode, or a DataLoopNameListNode, and ptr is a // pointer to the type of data node stored inside someNode.) // If it used to say this: someNode->erase( &ptr ); // Then change it to this: someNode->erase( someNode->iteratorFor(ptr) ); // If it used to say this: someNode->insert( &ptr , newPtr ); // Then change it to this: someNode->insert( someNode->iteratorFor( ptr ), newPtr );Again, it cannot be emphasised enough that this is a slow method not to be used repeatedly on large lists of things (like certain loops). This could have been implemented silently by making a copy constructor that would transform pointer-to into an iterator but I chose to deliberately not do that. People using the new starlib2 should be alerted to this change and make the decision themselves as to whether to use this slower method or to rewrite the code to not use pointers.)
#<START-SKIP> #<END-SKIP>These directives must be typed exactly as shown, and must appear at the very start of a line, much like a C preprocessor directive. The section of the file that is contained between the #<START-SKIP> and the #<END-SKIP> directives will be stored as an inaccessable string to be dumped out later when Unparse() is called. There exist no methods for getting access to these strings. They are hidden from the application program that is using starlib2.
To be legal, the remainder of the file after the skipped section has been "removed" must still form valid star syntax. For example, the following would be illegal:
data_ex save_example1 _tag1 value1 loop_ _looptag1 _looptag2 lval1 lval2 #<START-SKIP> lval3 lval4 lval5 lval6 stop_ save_ #<END-SKIP>The above example is illegal because it cuts out the trailing save_ from the saveframe called save_example1, leaving behind invalid STAR syntax.
This, however, would be perfectly legal, and is how this feature is intended to be used - imagine that you had 5 saveframes in the file and you were only interested in the one called "save_data4":
data_ex #<START-SKIP> save_data1 ...assume there is a lot of data here... save_ save_data2 ...assume there is a lot of data here... save_ save_data3 ...assume there is a lot of data here... save_ #<END-SKIP> save_data4 ...assume there is data here that the program is interested in... save_ #<START-SKIP> save_data5 ...assume there is a lot of data here... save_ #<END-SKIP>