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