#include ///////////////////////////////////////////////////////////////////// // TCL quoting // // These functions allow you to write a string from C++ in such a way // that it can be read back into TCL as a list. This includes // quoting of all characters which are special to a list. This also // quotes characters which could be confusing to a human reader. // // Why TCL style quoting? These functions were originally created // for use in a custom log file. Of course this allows us to produce // files which can be read in by TCL, even though the main program // does not use TCL. This format is also very readable by humans. // And this format is especially nice when outputting recursive // data structures. // // There are multiple legal ways to encode a list in TCL. (In fact // there are an infinite number of ways to encode most lists.) All // of these will be decoded to generate the same result. // // Our choices are generally similar to the choices used by TCL when // it converts a list to a string. We do not quote certain // characters, like [, so these routines are only good for producing // TCL data, not TCL code. We quote all unprintable characters, so a // human reader may read the output more easily. In particular, the // \n and \r character are quoted, so that you can use \n or \r\n as // a record separator. ///////////////////////////////////////////////////////////////////// // This encodes a single string the way that TCL quotes a list item. // If TCL will read in the result, this is not very interesting; // this is like making a list with one item, s. However, TCL-style // quoting can be useful in other places. std::string tclQuote(const std::string s); // This encodes a list as a string in a manner compatible with TCL. // start and end are an STL-style sequence of items which are, or // can be implicitly converted to, strings. template < class In > std::string tclList(In start, In end) { bool first = true; std::string result; for (; start != end; start++) { if (first) { first = false; } else { result += ' '; } result += tclQuote(*start); } return result; } // This encodes a list in the same way as above, but it allows you to do it // one entry at a time, like the lappend command in TCL. // // Some of these operations are slightly faster than the previous way of making // a list. Specifically, the integer versions are faster because we know that // an integer does not need to be quoted. But the primary reason for this // list is that it's just more convenient to have the conversion and the // container combined into one. // // The bulk of these operations are only required to avoid ambiguity, and // this really isn't as complicated as it may appear at first. // char * is converted to string in the obvious way. A character is treated // as a string that is one character long. All other integers are converted // to decimal. class TclList { private: std::string _s; void addSeperator(); public: operator std::string() const; TclList &operator <<(std::string s); TclList &operator <<(char ch); TclList &operator <<(unsigned char ch); TclList &operator <<(int i); TclList &operator <<(unsigned int i); TclList &operator <<(long int i); TclList &operator <<(unsigned long int i); TclList &operator <<(long long int i); TclList &operator <<(unsigned long long int i); void clear(); };