Color output.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 23 Nov 2010 10:37:03 +0000 (10:37 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 23 Nov 2010 10:37:03 +0000 (10:37 +0000)
formatter.hpp [new file with mode: 0644]
trace_model.cpp

diff --git a/formatter.hpp b/formatter.hpp
new file mode 100644 (file)
index 0000000..c1568a6
--- /dev/null
@@ -0,0 +1,162 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _FORMATTER_HPP_
+#define _FORMATTER_HPP_
+
+
+#include <iostream>
+
+
+namespace Formatter {
+
+/*
+ * See also http://bytes.com/topic/c/answers/63822-design-question-little-c-header-colorizing-text-linux-comments-ideas
+ */
+
+class Attribute {
+public:
+   virtual ~Attribute() {}
+
+   virtual std::ostream& apply(std::ostream& os) const { return os; }
+};
+
+
+enum Color {
+   RED,
+   GREEN,
+   BLUE,
+};
+
+
+class Formatter {
+public:
+   virtual ~Formatter() {}
+
+   virtual Attribute *normal(void) const { return new Attribute; }
+   virtual Attribute *bold(void) const { return new Attribute; }
+   virtual Attribute *italic(void) const { return new Attribute; }
+   virtual Attribute *color(Color color) const { return new Attribute; }
+};
+
+class AnsiAttribute : public Attribute {
+protected:
+   const char *escape;
+public:
+   AnsiAttribute(const char *_escape) : escape(_escape) {}
+   std::ostream & apply(std::ostream& os) const {
+      return os << "\33[" << escape;
+   }
+};
+
+
+/**
+ * Formatter for plain-text files which outputs ANSI escape codes. See
+ * http://en.wikipedia.org/wiki/ANSI_escape_code for more information
+ * concerning ANSI escape codes.
+ */
+class AnsiFormatter : public Formatter {
+protected:
+public:
+   virtual Attribute *normal(void) const { return new AnsiAttribute("0m"); }
+   virtual Attribute *bold(void) const { return new AnsiAttribute("1m"); }
+   virtual Attribute *italic(void) const { return new AnsiAttribute("3m"); }
+   virtual Attribute *color(Color c) const { 
+      static const char *color_escapes[] = {
+         "31m", /* red */
+         "32m", /* green */
+         "34m", /* blue */
+      };
+      return new AnsiAttribute(color_escapes[c]); 
+   }
+};
+
+
+inline std::ostream& operator<<(std::ostream& os, const Attribute *attr) {
+   return attr->apply(os);
+}
+
+
+#ifdef WIN32
+
+#include <windows.h>
+
+class WindowsAttribute : public Attribute {
+protected:
+   WORD wAttributes;
+public:
+   WindowsAttribute(WORD _wAttributes) : wAttributes(_wAttributes) {}
+   std::ostream & apply(std::ostream& os) const {
+      DWORD nStdHandleOutput;
+      if (os == std::cout) {
+         nStdHandleOutput = STD_OUTPUT_HANDLE;
+      } else if (os == std::cerr) {
+         nStdHandleOutput = STD_ERROR_HANDLE;
+      } else {
+         return os;
+      }
+
+      HANDLE hConsoleOutput = GetStdHandle(nStdHandleOutput);
+      SetConsoleTextAttribute(hConsoleOutput, wAttributes);
+   }
+};
+
+
+/**
+ * Formatter for the Windows Console.
+ */
+class WindowsFormatter : public Formatter {
+protected:
+public:
+   virtual Attribute *normal(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); }
+   virtual Attribute *bold(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); }
+   virtual Attribute *italic(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); }
+   virtual Attribute *color(Color c) const { 
+      static const WORD color_escapes[] = {
+         FOREGROUND_RED | FOREGROUND_INTENSITY,
+         FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+         FOREGROUND_BLUE | FOREGROUND_INTENSITY, 
+      };
+      return new WindowsAttribute(color_escapes[c]); 
+   }
+};
+
+#endif
+
+
+inline Formatter *defaultFormatter(void) {
+#ifdef WIN32
+   return new WindowsFormatter;
+#else
+   return new AnsiFormatter;
+#endif
+}
+
+
+} /* namespace Formatter */
+
+
+#endif /* _FORMATTER_HPP_ */
index 213c872..63968b7 100644 (file)
@@ -24,6 +24,7 @@
  **************************************************************************/
 
 
+#include "formatter.hpp"
 #include "trace_model.hpp"
 
 
@@ -69,39 +70,63 @@ void Blob::visit(Visitor &visitor) {
 
 class Dumper : public Visitor
 {
-public:
+protected:
    std::ostream &os;
+   Formatter::Formatter *formatter;
+   Formatter::Attribute *normal;
+   Formatter::Attribute *bold;
+   Formatter::Attribute *italic;
+   Formatter::Attribute *red;
+   Formatter::Attribute *pointer;
+   Formatter::Attribute *literal;
 
-   Dumper() : os(std::cout) {}
+public:
+   Dumper(std::ostream &_os) : os(_os) {
+      formatter = Formatter::defaultFormatter();
+      normal = formatter->normal();
+      bold = formatter->bold();
+      italic = formatter->italic();
+      red = formatter->color(Formatter::RED);
+      pointer = formatter->color(Formatter::GREEN);
+      literal = formatter->color(Formatter::BLUE);
+   }
 
-   Dumper(std::ostream &_os) : os(_os) {}
+   ~Dumper() {
+      delete normal;
+      delete bold;
+      delete italic;
+      delete red;
+      delete pointer;
+      delete literal;
+      delete formatter;
+   }
 
    void visit(Null *node) {
       os << "NULL";
    }
 
    void visit(Bool *node) {
-      os << (node->value ? "true" : "false");
+      os << literal << (node->value ? "true" : "false") << normal;
    }
 
    void visit(SInt *node) {
-      os << node->value;
+      os << literal << node->value << normal;
    }
 
    void visit(UInt *node) {
-      os << node->value;
+      os << literal << node->value << normal;
    }
 
    void visit(Float *node) {
-      os << node->value;
+      os << literal << node->value << normal;
    }
 
    void visit(String *node) {
-      os << '"' << node->value << '"';
+      os << literal << '"' << node->value << '"' << normal;
    }
 
    void visit(Const *node) {
-      os << node->name;
+      os << literal << node->name << normal;
    }
 
    void visit(Array *array) {
@@ -122,7 +147,23 @@ public:
    }
    
    void visit(Blob *blob) {
-      os << "... " << blob->size;
+      os << pointer << "blob(" << blob->size << ")" << normal;
+   }
+
+   void visit(Call *call) {
+      const char *sep = "";
+      os << bold << call->name << normal << "(";
+      for (std::list<Arg>::iterator it = call->args.begin(); it != call->args.end(); ++it) {
+         os << sep << italic << it->first << normal << " = ";
+         it->second->visit(*this);
+         sep = ", ";
+      }
+      os << ")";
+      if (call->ret) {
+         os << " = ";
+         call->ret->visit(*this);
+      }
+      os << "\n";
    }
 };
 
@@ -214,17 +255,8 @@ Value & Call::arg(const char *name) {
 }
 
 std::ostream & operator <<(std::ostream &os, Call &call) {
-   const char *sep = "";
-   os << call.name << "(";
-   for (std::list<Arg>::iterator it = call.args.begin(); it != call.args.end(); ++it) {
-      os << sep << it->first << " = " << it->second;
-      sep = ", ";
-   }
-   os << ")";
-   if (call.ret) {
-      os << " = " << call.ret;
-   }
-   os << "\n";
+   Dumper d(os);
+   d.visit(&call);
    return os;
 }