Mercurial > ~dholland > hg > ag > index.cgi
diff oldclasslib/include/charsink.h @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children | 607e3be6bad8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/oldclasslib/include/charsink.h Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,231 @@ +/* + * AnaGram, a System for Syntax Directed Programming + * + * Character Sink Class Definitions + * + * Copyright 1993 Parsifal Software. All Rights Reserved. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef CHARSINK_H +#define CHARSINK_H + +#include <stdio.h> +#include <assert.h> + + +// Class Definition for character_sink + +class character_sink { +public: + virtual ~character_sink() {} + virtual character_sink& operator << (int c) = 0; + virtual character_sink& operator << (const char *str) = 0; + virtual character_sink& operator << (const unsigned char *str) = 0; + virtual character_sink& printf(const char *, ...) = 0; +}; + + +// Class Definition for output_file + +class output_file : public character_sink { +private: + FILE *file; + char *name; + int error_flag; + int copy_flag; // is it live or memorex? + +public: + +// Constructors + + output_file() { + file = stdout; + error_flag = copy_flag = 0; + } + + output_file(char *path) : character_sink() { + name = path; + if (name == NULL) file = stdout; + else file = fopen(name = path, "wt"); + if (file == NULL) file = stdout; + error_flag = copy_flag = 0; + } + + output_file(output_file &f) : character_sink() { + *this = f; + copy_flag++; + } + + +// Destructor + + ~output_file() {if (copy_flag == 0) fclose(file);} + + +// Xmit data to sink + + character_sink& operator << (int c) { + error_flag = putc((char) c,file); + return *this; + } + + character_sink& operator << (const char *str) { + fputs(str,file); + return *this; + } + + character_sink& operator << (const unsigned char *str) { + fputs((const char *)str, file); + return *this; + } + + character_sink& printf(const char *, ...); + + +// Check for error + + friend int error(output_file &f); +}; + +inline int error(output_file &f) { + return f.error_flag < 0; +} + +class string_accumulator : public character_sink { +private: + char *cs; // character storage + unsigned *xs; // index storage + unsigned csx; // next available character + unsigned xsx; // next available index + unsigned csmax; // max number of characters + unsigned xsmax; // max number of indices + int copy_flag; // is it live or is it memorex? + +public: + +// Constructor + + string_accumulator(int nc, int nx = 1); + string_accumulator(const string_accumulator &); + + +// Destructor + + ~string_accumulator(); + + +// Reset string_accumulator + + friend string_accumulator &reset(string_accumulator &); + + +// Change stack level + + string_accumulator& operator ++(){ // preincrement stack level + assert(copy_flag == 0); + assert(xsx); + xs[--xsx] = csx; + return *this; + } + + string_accumulator operator ++ (int); // postincrement stack level + + string_accumulator &operator -- () { // predecrement stack level + assert(copy_flag == 0); + csx = xs[xsx++]; // discard top string + assert(xsx < xsmax); + return *this; + } + + string_accumulator operator -- (int); // post decrement stack level + +// Append data to stack + + character_sink& operator << (int c) { // append char to top string + assert(copy_flag == 0); + assert(csx < csmax); + cs[csx++] = (char) c; + return *this; + } + + character_sink &operator << (const char *str); // append string to top string + + character_sink &operator << (const unsigned char *str); + + character_sink &operator << (string_accumulator &s) { + assert(this != &s); // prevent disaster + return *this << s.top(); + } + + character_sink &printf(const char *, ...); + + +// Pop character from stack + + string_accumulator &operator >> (int &c); // pop last character + + +// Access character on stack + + char &operator [] (unsigned); // inspect character + + +// Retrieve pointer to top string + +// See README.txt +#if 0 + operator char *() const { // pointer to top string + cs[csx] = 0; + return &cs[xs[xsx]]; + } + + operator unsigned char *() const { // pointer to top string + cs[csx] = 0; + return (unsigned char *) &cs[xs[xsx]]; + } +#else + char *top() const { + cs[csx] = 0; + return &cs[xs[xsx]]; + } +#endif + + +// Concatenate strings + + friend string_accumulator& concat(string_accumulator &); + + +// Make permanent copy of string + + friend char *copy(const string_accumulator &); + + +// Get length of string + + friend unsigned size(const string_accumulator &); + +}; + +inline unsigned size(const string_accumulator &s) { + assert(s.xsx < s.xsmax); + return s.csx - s.xs[s.xsx]; +} + +#endif