]> git.cworth.org Git - apitrace/commitdiff
Put all common code in a subdirectory.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Wed, 21 Sep 2011 06:46:50 +0000 (07:46 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Wed, 21 Sep 2011 06:46:50 +0000 (07:46 +0100)
51 files changed:
CMakeLists.txt
common/formatter.hpp [new file with mode: 0644]
common/image.cpp [new file with mode: 0644]
common/image.hpp [new file with mode: 0644]
common/image_bmp.cpp [new file with mode: 0644]
common/image_png.cpp [new file with mode: 0644]
common/image_pnm.cpp [new file with mode: 0644]
common/json.hpp [new file with mode: 0644]
common/os.hpp [new file with mode: 0644]
common/os_posix.cpp [new file with mode: 0644]
common/os_win32.cpp [new file with mode: 0644]
common/trace_file.cpp [new file with mode: 0644]
common/trace_file.hpp [new file with mode: 0644]
common/trace_format.hpp [new file with mode: 0644]
common/trace_loader.cpp [new file with mode: 0644]
common/trace_loader.hpp [new file with mode: 0644]
common/trace_local_writer.cpp [new file with mode: 0644]
common/trace_model.cpp [new file with mode: 0644]
common/trace_model.hpp [new file with mode: 0644]
common/trace_model_writer.cpp [new file with mode: 0644]
common/trace_parser.cpp [new file with mode: 0644]
common/trace_parser.hpp [new file with mode: 0644]
common/trace_snappyfile.cpp [new file with mode: 0644]
common/trace_snappyfile.hpp [new file with mode: 0644]
common/trace_writer.cpp [new file with mode: 0644]
common/trace_writer.hpp [new file with mode: 0644]
formatter.hpp [deleted file]
image.cpp [deleted file]
image.hpp [deleted file]
image_bmp.cpp [deleted file]
image_png.cpp [deleted file]
image_pnm.cpp [deleted file]
json.hpp [deleted file]
os.hpp [deleted file]
os_posix.cpp [deleted file]
os_win32.cpp [deleted file]
trace_file.cpp [deleted file]
trace_file.hpp [deleted file]
trace_format.hpp [deleted file]
trace_loader.cpp [deleted file]
trace_loader.hpp [deleted file]
trace_local_writer.cpp [deleted file]
trace_model.cpp [deleted file]
trace_model.hpp [deleted file]
trace_model_writer.cpp [deleted file]
trace_parser.cpp [deleted file]
trace_parser.hpp [deleted file]
trace_snappyfile.cpp [deleted file]
trace_snappyfile.hpp [deleted file]
trace_writer.cpp [deleted file]
trace_writer.hpp [deleted file]

index 9c91c9077313b8ac333d0468b508c94a388102e0..360e8301bb3c6bc4090b66b08e2a1ea2162b68fe 100755 (executable)
@@ -163,7 +163,10 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
 ##############################################################################
 # Common libraries / utilities
 
-include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+include_directories (
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/common
+)
 
 add_custom_command (
     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
@@ -180,19 +183,19 @@ else (WIN32)
 endif (WIN32)
 
 add_library (common
-    trace_file.cpp
-    trace_snappyfile.cpp
-    trace_model.cpp
-    trace_parser.cpp
-    trace_writer.cpp
-    trace_local_writer.cpp
-    trace_model_writer.cpp
-    trace_loader.cpp
-    image.cpp
-    image_bmp.cpp
-    image_pnm.cpp
-    image_png.cpp
-    ${os}
+    common/trace_file.cpp
+    common/trace_snappyfile.cpp
+    common/trace_model.cpp
+    common/trace_parser.cpp
+    common/trace_writer.cpp
+    common/trace_local_writer.cpp
+    common/trace_model_writer.cpp
+    common/trace_loader.cpp
+    common/image.cpp
+    common/image_bmp.cpp
+    common/image_pnm.cpp
+    common/image_png.cpp
+    common/${os}
 )
 
 set_target_properties (common PROPERTIES
@@ -383,7 +386,6 @@ add_executable (glretrace
     glstate_params.cpp
     retrace.cpp
     ${glws}
-    image.cpp 
     ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
 )
 
diff --git a/common/formatter.hpp b/common/formatter.hpp
new file mode 100644 (file)
index 0000000..181e2d1
--- /dev/null
@@ -0,0 +1,174 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Helpers for coloring output.
+ */
+
+#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 void apply(std::ostream &) const {}
+};
+
+
+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) const { return new Attribute; }
+};
+
+
+class AnsiAttribute : public Attribute {
+protected:
+    const char *escape;
+public:
+    AnsiAttribute(const char *_escape) : escape(_escape) {}
+    void apply(std::ostream& os) const {
+        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) {
+    attr->apply(os);
+    return os;
+}
+
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+class WindowsAttribute : public Attribute {
+protected:
+    WORD wAttributes;
+public:
+    WindowsAttribute(WORD _wAttributes) : wAttributes(_wAttributes) {}
+    void 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;
+        }
+        HANDLE hConsoleOutput = GetStdHandle(nStdHandleOutput);
+        if (hConsoleOutput == INVALID_HANDLE_VALUE) {
+            return;
+        }
+
+        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(bool color = true) {
+    if (color) {
+#ifdef _WIN32
+        return new WindowsFormatter;
+#else
+        return new AnsiFormatter;
+#endif
+    } else {
+        return new Formatter;
+    }
+}
+
+
+} /* namespace Formatter */
+
+
+#endif /* _FORMATTER_HPP_ */
diff --git a/common/image.cpp b/common/image.cpp
new file mode 100644 (file)
index 0000000..4da9c13
--- /dev/null
@@ -0,0 +1,76 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <math.h>
+
+#include "image.hpp"
+
+
+namespace Image {
+
+
+double Image::compare(Image &ref)
+{
+    if (width != ref.width ||
+        height != ref.height ||
+        channels != ref.channels) {
+        return 0.0;
+    }
+
+    const unsigned char *pSrc = start();
+    const unsigned char *pRef = ref.start();
+
+    assert(channels >= 3);
+
+    unsigned long long error = 0;
+    for (unsigned y = 0; y < height; ++y) {
+        for (unsigned  x = 0; x < width; ++x) {
+            // FIXME: Ignore alpha channel until we are able to pick a visual
+            // that matches the traces
+            for (unsigned  c = 0; c < 3; ++c) {
+                int delta = pSrc[x*channels + c] - pRef[x*channels + c];
+                error += delta*delta;
+            }
+        }
+
+        pSrc += stride();
+        pRef += ref.stride();
+    }
+
+    double numerator = error*2 + 1;
+    double denominator = height*width*3ULL*255ULL*255ULL*2;
+    double quotient = numerator/denominator;
+
+    // Precision in bits
+    double precision = -log(quotient)/log(2.0);
+
+    return precision;
+}
+
+
+} /* namespace Image */
diff --git a/common/image.hpp b/common/image.hpp
new file mode 100644 (file)
index 0000000..dc53ec9
--- /dev/null
@@ -0,0 +1,115 @@
+/**************************************************************************
+ *
+ * Copyright 2008-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.
+ *
+ **************************************************************************/
+
+/*
+ * Image I/O.
+ */
+
+#ifndef _IMAGE_HPP_
+#define _IMAGE_HPP_
+
+
+#include <fstream>
+
+
+namespace Image {
+
+
+class Image {
+public:
+    unsigned width;
+    unsigned height;
+    unsigned channels;
+
+    // Flipped vertically or not
+    bool flipped;
+
+    // Pixels in RGBA format
+    unsigned char *pixels;
+
+    inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false) : 
+        width(w),
+        height(h),
+        channels(c),
+        flipped(f),
+        pixels(new unsigned char[h*w*c])
+    {}
+
+    inline ~Image() {
+        delete [] pixels;
+    }
+
+    inline unsigned char *start(void) {
+        return flipped ? pixels + (height - 1)*width*channels : pixels;
+    }
+
+    inline const unsigned char *start(void) const {
+        return flipped ? pixels + (height - 1)*width*channels : pixels;
+    }
+
+    inline unsigned char *end(void) {
+        return flipped ? pixels - width*channels : pixels + height*width*channels;
+    }
+
+    inline const unsigned char *end(void) const {
+        return flipped ? pixels - width*channels : pixels + height*width*channels;
+    }
+
+    inline signed stride(void) const {
+        return flipped ? -width*channels : width*channels;
+    }
+
+    bool writeBMP(const char *filename) const;
+
+    void writePNM(std::ostream &os, const char *comment = NULL) const;
+
+    inline bool writePNM(const char *filename, const char *comment = NULL) const {
+        std::ofstream os(filename, std::ofstream::binary);
+        if (!os) {
+            return false;
+        }
+        writePNM(os, comment);
+        return true;
+    }
+
+    bool writePNG(const char *filename) const;
+
+    double compare(Image &ref);
+};
+
+bool writePixelsToBuffer(unsigned char *pixels,
+                         unsigned w, unsigned h, unsigned numChannels,
+                         bool flipped,
+                         char **buffer,
+                         int *size);
+
+Image *
+readPNG(const char *filename);
+
+
+} /* namespace Image */
+
+
+#endif /* _IMAGE_HPP_ */
diff --git a/common/image_bmp.cpp b/common/image_bmp.cpp
new file mode 100644 (file)
index 0000000..346f39a
--- /dev/null
@@ -0,0 +1,139 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "image.hpp"
+
+
+namespace Image {
+
+
+#pragma pack(push,2)
+struct FileHeader {
+    uint16_t bfType;
+    uint32_t bfSize;
+    uint16_t bfReserved1;
+    uint16_t bfReserved2;
+    uint32_t bfOffBits;
+};
+#pragma pack(pop)
+
+struct InfoHeader {
+    uint32_t biSize;
+    int32_t biWidth;
+    int32_t biHeight;
+    uint16_t biPlanes;
+    uint16_t biBitCount;
+    uint32_t biCompression;
+    uint32_t biSizeImage;
+    int32_t biXPelsPerMeter;
+    int32_t biYPelsPerMeter;
+    uint32_t biClrUsed;
+    uint32_t biClrImportant;
+};
+
+struct Pixel {
+    uint8_t rgbBlue;
+    uint8_t rgbGreen;
+    uint8_t rgbRed;
+    uint8_t rgbAlpha;
+};
+
+
+bool
+Image::writeBMP(const char *filename) const {
+    assert(channels == 4);
+
+    struct FileHeader bmfh;
+    struct InfoHeader bmih;
+    unsigned x, y;
+
+    bmfh.bfType = 0x4d42;
+    bmfh.bfSize = 14 + 40 + height*width*4;
+    bmfh.bfReserved1 = 0;
+    bmfh.bfReserved2 = 0;
+    bmfh.bfOffBits = 14 + 40;
+
+    bmih.biSize = 40;
+    bmih.biWidth = width;
+    bmih.biHeight = height;
+    bmih.biPlanes = 1;
+    bmih.biBitCount = 32;
+    bmih.biCompression = 0;
+    bmih.biSizeImage = height*width*4;
+    bmih.biXPelsPerMeter = 0;
+    bmih.biYPelsPerMeter = 0;
+    bmih.biClrUsed = 0;
+    bmih.biClrImportant = 0;
+
+    std::ofstream stream(filename, std::ofstream::binary);
+
+    if (!stream) {
+        return false;
+    }
+
+    stream.write((const char *)&bmfh, 14);
+    stream.write((const char *)&bmih, 40);
+
+    unsigned stride = width*4;
+
+    if (flipped) {
+        for (y = 0; y < height; ++y) {
+            const unsigned char *ptr = pixels + y * stride;
+            for (x = 0; x < width; ++x) {
+                struct Pixel pixel;
+                pixel.rgbRed   = ptr[x*4 + 0];
+                pixel.rgbGreen = ptr[x*4 + 1];
+                pixel.rgbBlue  = ptr[x*4 + 2];
+                pixel.rgbAlpha = ptr[x*4 + 3];
+                stream.write((const char *)&pixel, 4);
+            }
+        }
+    } else {
+        y = height;
+        while (y--) {
+            const unsigned char *ptr = pixels + y * stride;
+            for (x = 0; x < width; ++x) {
+                struct Pixel pixel;
+                pixel.rgbRed   = ptr[x*4 + 0];
+                pixel.rgbGreen = ptr[x*4 + 1];
+                pixel.rgbBlue  = ptr[x*4 + 2];
+                pixel.rgbAlpha = ptr[x*4 + 3];
+                stream.write((const char *)&pixel, 4);
+            }
+        }
+    }
+
+    stream.close();
+
+    return true;
+}
+
+
+} /* namespace Image */
diff --git a/common/image_png.cpp b/common/image_png.cpp
new file mode 100644 (file)
index 0000000..fd22213
--- /dev/null
@@ -0,0 +1,312 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-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.
+ *
+ **************************************************************************/
+
+
+#include <zlib.h>
+#include <png.h>
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <fstream>
+
+#include "image.hpp"
+
+
+namespace Image {
+
+
+bool
+Image::writePNG(const char *filename) const {
+    FILE *fp;
+    png_structp png_ptr;
+    png_infop info_ptr;
+
+    fp = fopen(filename, "wb");
+    if (!fp)
+        goto no_fp;
+
+    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr)
+        goto no_png;
+
+    info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr,  NULL);
+        goto no_png;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        goto no_png;
+    }
+
+    png_init_io(png_ptr, fp);
+
+    int color_type;
+    switch (channels) {
+    case 4:
+        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+        break;
+    case 3:
+        color_type = PNG_COLOR_TYPE_RGB;
+        break;
+    case 2:
+        color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+        break;
+    case 1:
+        color_type = PNG_COLOR_TYPE_GRAY;
+        break;
+    default:
+        assert(0);
+        return false;
+    }
+
+    png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type,
+        PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+    png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
+
+    png_write_info(png_ptr, info_ptr);
+
+    if (!flipped) {
+        for (unsigned y = 0; y < height; ++y) {
+            png_bytep row = (png_bytep)(pixels + y*width*channels);
+            png_write_rows(png_ptr, &row, 1);
+        }
+    } else {
+        unsigned y = height;
+        while (y--) {
+            png_bytep row = (png_bytep)(pixels + y*width*channels);
+            png_write_rows(png_ptr, &row, 1);
+        }
+    }
+
+    png_write_end(png_ptr, info_ptr);
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+
+    fclose(fp);
+    return true;
+
+no_png:
+    fclose(fp);
+no_fp:
+    return false;
+}
+
+
+Image *
+readPNG(const char *filename)
+{
+    FILE *fp;
+    png_structp png_ptr;
+    png_infop info_ptr;
+    png_infop end_info;
+    Image *image;
+
+    fp = fopen(filename, "rb");
+    if (!fp)
+        goto no_fp;
+
+    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr)
+        goto no_png;
+
+    info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_read_struct(&png_ptr, NULL, NULL);
+        goto no_png;
+    }
+
+    end_info = png_create_info_struct(png_ptr);
+    if (!end_info) {
+        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+        goto no_png;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+        goto no_png;
+    }
+
+    png_init_io(png_ptr, fp);
+
+    png_read_info(png_ptr, info_ptr);
+
+    png_uint_32 width, height;
+    int bit_depth, color_type, interlace_type, compression_type, filter_method;
+
+    png_get_IHDR(png_ptr, info_ptr,
+                 &width, &height,
+                 &bit_depth, &color_type, &interlace_type,
+                 &compression_type, &filter_method);
+
+    image = new Image(width, height);
+    if (!image)
+        goto no_image;
+
+    /* Convert to RGBA8 */
+    if (color_type == PNG_COLOR_TYPE_PALETTE)
+        png_set_palette_to_rgb(png_ptr);
+    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+        png_set_expand_gray_1_2_4_to_8(png_ptr);
+    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+        png_set_tRNS_to_alpha(png_ptr);
+    if (bit_depth == 16)
+        png_set_strip_16(png_ptr);
+
+    for (unsigned y = 0; y < height; ++y) {
+        png_bytep row = (png_bytep)(image->pixels + y*width*4);
+        png_read_row(png_ptr, row, NULL);
+    }
+
+    png_read_end(png_ptr, info_ptr);
+    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+    fclose(fp);
+    return image;
+
+no_image:
+    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+no_png:
+    fclose(fp);
+no_fp:
+    return NULL;
+}
+
+
+struct png_tmp_buffer
+{
+    char *buffer;
+    size_t size;
+};
+
+static void
+pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+    struct png_tmp_buffer *buf = (struct png_tmp_buffer*) png_get_io_ptr(png_ptr);
+    size_t nsize = buf->size + length;
+
+    /* allocate or grow buffer */
+    if (buf->buffer)
+        buf->buffer = (char*)realloc(buf->buffer, nsize);
+    else
+        buf->buffer = (char*)malloc(nsize);
+
+    if (!buf->buffer)
+        png_error(png_ptr, "Buffer allocation error");
+
+    memcpy(buf->buffer + buf->size, data, length);
+    buf->size += length;
+}
+
+bool writePixelsToBuffer(unsigned char *pixels,
+                         unsigned width, unsigned height, unsigned numChannels,
+                         bool flipped,
+                         char **buffer,
+                         int *size)
+{
+    struct png_tmp_buffer png_mem;
+    png_structp png_ptr;
+    png_infop info_ptr;
+    int type;
+
+    png_mem.buffer = NULL;
+    png_mem.size = 0;
+
+    switch (numChannels) {
+    case 4:
+        type = PNG_COLOR_TYPE_RGB_ALPHA;
+        break;
+    case 3:
+        type = PNG_COLOR_TYPE_RGB;
+        break;
+    case 2:
+        type = PNG_COLOR_TYPE_GRAY_ALPHA;
+        break;
+    case 1:
+        type = PNG_COLOR_TYPE_GRAY;
+        break;
+    default:
+        goto no_png;
+    }
+
+    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr)
+        goto no_png;
+
+    info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr,  NULL);
+        goto no_png;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        goto no_png;
+    }
+
+    png_set_write_fn(png_ptr, &png_mem, pngWriteCallback, NULL);
+
+    png_set_IHDR(png_ptr, info_ptr, width, height, 8,
+                 type, PNG_INTERLACE_NONE,
+                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+    png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
+
+    png_write_info(png_ptr, info_ptr);
+
+    if (!flipped) {
+        for (unsigned y = 0; y < height; ++y) {
+            png_bytep row = (png_bytep)(pixels + y*width*numChannels);
+            png_write_rows(png_ptr, &row, 1);
+        }
+    } else {
+        unsigned y = height;
+        while (y--) {
+            png_bytep row = (png_bytep)(pixels + y*width*numChannels);
+            png_write_rows(png_ptr, &row, 1);
+        }
+    }
+
+    png_write_end(png_ptr, info_ptr);
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+
+    *buffer = png_mem.buffer;
+    *size = png_mem.size;
+
+    return true;
+
+no_png:
+    *buffer = NULL;
+    *size = 0;
+
+    if (png_mem.buffer)
+        free(png_mem.buffer);
+    return false;
+}
+
+} /* namespace Image */
diff --git a/common/image_pnm.cpp b/common/image_pnm.cpp
new file mode 100644 (file)
index 0000000..5397a1a
--- /dev/null
@@ -0,0 +1,112 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "image.hpp"
+
+
+namespace Image {
+
+/**
+ * http://en.wikipedia.org/wiki/Netpbm_format
+ * http://netpbm.sourceforge.net/doc/ppm.html
+ */
+void
+Image::writePNM(std::ostream &os, const char *comment) const {
+    assert(channels == 1 || channels >= 3);
+
+    os << (channels == 1 ? "P5" : "P6") << "\n";
+    if (comment) {
+        os << "#" << comment << "\n";
+    }
+    os << width << " " << height << "\n";
+    os << "255" << "\n";
+
+    const unsigned char *row;
+
+    if (channels == 1 || channels == 3) {
+        for (row = start(); row != end(); row += stride()) {
+            os.write((const char *)row, width*channels);
+        }
+    } else {
+        unsigned char *tmp = new unsigned char[width*3];
+        if (channels == 4) {
+            for (row = start(); row != end(); row += stride()) {
+                const uint32_t *src = (const uint32_t *)row;
+                uint32_t *dst = (uint32_t *)tmp;
+                unsigned x;
+                for (x = 0; x + 4 <= width; x += 4) {
+                    /*
+                     * It's much faster to access dwords than bytes.
+                     *
+                     * FIXME: Big-endian version.
+                     */
+
+                    uint32_t rgba0 = *src++ & 0xffffff;
+                    uint32_t rgba1 = *src++ & 0xffffff;
+                    uint32_t rgba2 = *src++ & 0xffffff;
+                    uint32_t rgba3 = *src++ & 0xffffff;
+                    uint32_t rgb0 = rgba0
+                                  | (rgba1 << 24);
+                    uint32_t rgb1 = (rgba1 >> 8)
+                                  | (rgba2 << 16);
+                    uint32_t rgb2 = (rgba2 >> 16)
+                                  | (rgba3 << 8);
+                    *dst++ = rgb0;
+                    *dst++ = rgb1;
+                    *dst++ = rgb2;
+                }
+                for (; x < width; ++x) {
+                    tmp[x*3 + 0] = row[x*4 + 0];
+                    tmp[x*3 + 1] = row[x*4 + 1];
+                    tmp[x*3 + 2] = row[x*4 + 2];
+                }
+                os.write((const char *)tmp, width*3);
+            }
+        } else if (channels == 2) {
+            for (row = start(); row != end(); row += stride()) {
+                const unsigned char *src = row;
+                unsigned char *dst = tmp;
+                for (unsigned x = 0; x < width; ++x) {
+                    *dst++ = *src++;
+                    *dst++ = *src++;
+                    *dst++ = 0;
+                }
+                os.write((const char *)tmp, width*3);
+            }
+        } else {
+            assert(0);
+        }
+        delete [] tmp;
+    }
+}
+
+
+} /* namespace Image */
diff --git a/common/json.hpp b/common/json.hpp
new file mode 100644 (file)
index 0000000..9e6b960
--- /dev/null
@@ -0,0 +1,337 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Trace writing functions.
+ */
+
+#ifndef _JSON_HPP_
+#define _JSON_HPP_
+
+#include <assert.h>
+#include <stddef.h>
+#include <wchar.h>
+
+#include <iomanip>
+#include <ostream>
+#include <string>
+
+
+class JSONWriter
+{
+private:
+    std::ostream &os;
+
+    int level;
+    bool value;
+    char space;
+
+    void newline(void) {
+        os << "\n";
+        for (int i = 0; i < level; ++i) 
+            os << "  ";
+    }
+
+    void separator(void) {
+        if (value) {
+            os << ",";
+            switch (space) {
+            case '\0':
+                break;
+            case '\n':
+                newline();
+                break;
+            default:
+                os << space;
+                break;
+            }
+        } else {
+            if (space == '\n') {
+                newline();
+            }
+        }
+    }
+
+    void escapeAsciiString(const char *str) {
+        os << "\"";
+
+        const unsigned char *src = (const unsigned char *)str;
+        unsigned char c;
+        while ((c = *src++)) {
+            if ((c == '\"') ||
+                (c == '\\')) {
+                // escape character
+                os << '\\' << (unsigned char)c;
+            } else if ((c >= 0x20 && c <= 0x7e) ||
+                        c == '\t' ||
+                        c == '\r' ||
+                        c == '\n') {
+                // pass-through character
+                os << (unsigned char)c;
+            } else {
+                assert(0);
+                os << "?";
+            }
+        }
+
+        os << "\"";
+    }
+
+    void escapeUnicodeString(const char *str) {
+        os << "\"";
+
+        const char *locale = setlocale(LC_CTYPE, "");
+        const char *src = str;
+        mbstate_t state;
+
+        memset(&state, 0, sizeof state);
+
+        do {
+            // Convert characters one at a time in order to recover from
+            // conversion errors
+            wchar_t c;
+            size_t written = mbsrtowcs(&c, &src, 1, &state);
+            if (written == 0) {
+                // completed
+                break;
+            } if (written == (size_t)-1) {
+                // conversion error -- skip 
+                os << "?";
+                do {
+                    ++src;
+                } while (*src & 0x80);
+            } else if ((c == '\"') ||
+                       (c == '\\')) {
+                // escape character
+                os << '\\' << (unsigned char)c;
+            } else if ((c >= 0x20 && c <= 0x7e) ||
+                        c == '\t' ||
+                        c == '\r' ||
+                        c == '\n') {
+                // pass-through character
+                os << (unsigned char)c;
+            } else {
+                // unicode
+                os << "\\u" << std::setfill('0') << std::hex << std::setw(4) << (unsigned)c;
+                os << std::dec;
+            }
+        } while (src);
+
+        setlocale(LC_CTYPE, locale);
+
+        os << "\"";
+    }
+
+    void encodeBase64String(const unsigned char *bytes, size_t size) {
+        const char *table64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+        unsigned char c0, c1, c2, c3;
+        char buf[4];
+        unsigned written;
+
+        os << "\"";
+
+        written = 0;
+        while (size >= 3) {
+            c0 = bytes[0] >> 2;
+            c1 = ((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xf0) >> 4);
+            c2 = ((bytes[1] & 0x0f) << 2) | ((bytes[2] & 0xc0) >> 6);
+            c3 = bytes[2] & 0x3f;
+
+            buf[0] = table64[c0];
+            buf[1] = table64[c1];
+            buf[2] = table64[c2];
+            buf[3] = table64[c3];
+
+            os.write(buf, 4);
+
+            bytes += 3;
+            size -= 3;
+            ++written;
+
+            if (written >= 76/4 && size) {
+                os << "\n";
+                written = 0;
+            }
+        }
+
+        if (size > 0) {
+            c0 = bytes[0] >> 2;
+            c1 = ((bytes[0] & 0x03) << 4);
+            buf[2] = '=';
+            buf[3] = '=';
+            
+            if (size > 1) {
+                c1 |= ((bytes[1] & 0xf0) >> 4);
+                c2 = ((bytes[1] & 0x0f) << 2);
+                if (size > 2) {
+                    c2 |= ((bytes[2] & 0xc0) >> 6);
+                    c3 = bytes[2] & 0x3f;
+                    buf[3] = table64[c3];
+                }
+                buf[2] = table64[c2];
+            }
+            buf[1] = table64[c1];
+            buf[0] = table64[c0];
+
+            os.write(buf, 4);
+        }
+
+        os << "\"";
+    }
+
+public:
+    JSONWriter(std::ostream &_os) : 
+        os(_os), 
+        level(0),
+        value(false),
+        space(0)
+    {
+        beginObject();
+    }
+
+    ~JSONWriter() {
+        endObject();
+        newline();
+    }
+
+    inline void beginObject() {
+        separator();
+        os << "{";
+        ++level;
+        value = false;
+    }
+
+    inline void endObject() {
+        --level;
+        if (value)
+            newline();
+        os << "}";
+        value = true;
+        space = '\n';
+    }
+
+    inline void beginMember(const char * name) {
+        space = 0;
+        separator();
+        newline();
+        escapeAsciiString(name);
+        os << ": ";
+        value = false;
+    }
+
+    inline void beginMember(const std::string &name) {
+        beginMember(name.c_str());
+    }
+
+    inline void endMember(void) {
+        assert(value);
+        value = true;
+        space = 0;
+    }
+
+    inline void beginArray() {
+        separator();
+        os << "[";
+        ++level;
+        value = false;
+        space = 0;
+    }
+
+    inline void endArray(void) {
+        --level;
+        if (space == '\n') {
+            newline();
+        }
+        os << "]";
+        value = true;
+        space = '\n';
+    }
+
+    inline void writeString(const char *s) {
+        separator();
+        escapeUnicodeString(s);
+        value = true;
+        space = ' ';
+    }
+
+    inline void writeString(const std::string &s) {
+        writeString(s.c_str());
+    }
+
+    inline void writeBase64(const void *bytes, size_t size) {
+        separator();
+        encodeBase64String((const unsigned char *)bytes, size);
+        value = true;
+        space = ' ';
+    }
+
+    inline void writeNull(void) {
+        separator();
+        os << "null";
+        value = true;
+        space = ' ';
+    }
+
+    inline void writeBool(bool b) {
+        separator();
+        os << (b ? "true" : "false");
+        value = true;
+        space = ' ';
+    }
+
+    template<class T>
+    inline void writeNumber(T n) {
+        if (n != n) {
+            // NaN
+            writeNull();
+        } else {
+            separator();
+            os << std::dec << std::setprecision(9) << n;
+            value = true;
+            space = ' ';
+        }
+    }
+    
+    inline void writeStringMember(const char *name, const char *s) {
+        beginMember(name);
+        writeString(s);
+        endMember();
+    }
+
+    inline void writeBoolMember(const char *name, bool b) {
+        beginMember(name);
+        writeBool(b);
+        endMember();
+    }
+
+    template<class T>
+    inline void writeNumberMember(const char *name, T n) {
+        beginMember(name);
+        writeNumber(n);
+        endMember();
+    }
+};
+
+#endif /* _JSON_HPP_ */
diff --git a/common/os.hpp b/common/os.hpp
new file mode 100644 (file)
index 0000000..8e487b5
--- /dev/null
@@ -0,0 +1,98 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Simple OS abstraction layer.
+ */
+
+#ifndef _OS_HPP_
+#define _OS_HPP_
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+#define PATH_SEP '\\'
+#else /* !_WIN32 */
+#define PATH_SEP '/'
+#endif /* !_WIN32 */
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+namespace OS {
+
+void AcquireMutex(void);
+
+void ReleaseMutex(void);
+
+bool GetProcessName(char *str, size_t size);
+bool GetCurrentDir(char *str, size_t size);
+
+void DebugMessage(const char *format, ...)
+#ifdef __GNUC__
+    __attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+#if defined _WIN32 || defined __CYGWIN__
+  /* We always use .def files on windows for now */
+  #if 0
+  #define PUBLIC __declspec(dllexport)
+  #else
+  #define PUBLIC
+  #endif
+  #define PRIVATE
+#else
+  #if __GNUC__ >= 4
+    #define PUBLIC __attribute__ ((visibility("default")))
+    #define PRIVATE __attribute__ ((visibility("hidden")))
+  #else
+    #define PUBLIC
+    #define PRIVATE
+  #endif
+#endif
+
+/**
+ * Get the current time in microseconds from an unknown base.
+ */
+long long GetTime(void);
+
+void Abort(void);
+
+void SetExceptionCallback(void (*callback)(void));
+void ResetExceptionCallback(void);
+
+} /* namespace OS */
+
+#endif /* _OS_HPP_ */
diff --git a/common/os_posix.cpp b/common/os_posix.cpp
new file mode 100644 (file)
index 0000000..98a790b
--- /dev/null
@@ -0,0 +1,236 @@
+/**************************************************************************
+ *
+ * Copyright 2010-2011 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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
+#include "os.hpp"
+
+
+namespace OS {
+
+
+static pthread_mutex_t 
+mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+void
+AcquireMutex(void)
+{
+    pthread_mutex_lock(&mutex);
+}
+
+
+void
+ReleaseMutex(void)
+{
+    pthread_mutex_unlock(&mutex);
+}
+
+
+bool
+GetProcessName(char *str, size_t size)
+{
+    char szProcessPath[PATH_MAX + 1];
+    char *lpProcessName;
+
+    // http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
+#ifdef __APPLE__
+    uint32_t len = sizeof szProcessPath;
+    if (_NSGetExecutablePath(szProcessPath, &len) != 0) {
+        *str = 0;
+        return false;
+    }
+#else
+    ssize_t len;
+    len = readlink("/proc/self/exe", szProcessPath, sizeof(szProcessPath) - 1);
+    if (len == -1) {
+        // /proc/self/exe is not available on setuid processes, so fallback to
+        // /proc/self/cmdline.
+        int fd = open("/proc/self/cmdline", O_RDONLY);
+        if (fd >= 0) {
+            len = read(fd, szProcessPath, sizeof(szProcessPath) - 1);
+            close(fd);
+        }
+    }
+    if (len <= 0) {
+        snprintf(str, size, "%i", (int)getpid());
+        return true;
+    }
+#endif
+    szProcessPath[len] = 0;
+
+    lpProcessName = strrchr(szProcessPath, '/');
+    lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
+
+    strncpy(str, lpProcessName, size);
+    if (size)
+        str[size - 1] = 0;
+
+    return true;
+}
+
+bool
+GetCurrentDir(char *str, size_t size)
+{
+    char *ret;
+    ret = getcwd(str, size);
+    str[size - 1] = 0;
+    return ret ? true : false;
+}
+
+void
+DebugMessage(const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    fflush(stdout);
+    vfprintf(stderr, format, ap);
+    va_end(ap);
+}
+
+long long GetTime(void)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return tv.tv_usec + tv.tv_sec*1000000LL;
+}
+
+void
+Abort(void)
+{
+    exit(0);
+}
+
+
+static void (*gCallback)(void) = NULL;
+
+#define NUM_SIGNALS 16
+
+struct sigaction old_actions[NUM_SIGNALS];
+
+
+/*
+ * See also:
+ * - http://sourceware.org/git/?p=glibc.git;a=blob;f=debug/segfault.c
+ * - http://ggi.cvs.sourceforge.net/viewvc/ggi/ggi-core/libgg/gg/cleanup.c?view=markup
+ */
+static void signal_handler(int sig, siginfo_t *info, void *context)
+{
+    static int recursion_count = 0;
+
+    fprintf(stderr, "signal_handler: sig = %i\n", sig);
+
+    if (recursion_count) {
+        fprintf(stderr, "recursion with sig %i\n", sig);
+    } else {
+        if (gCallback) {
+            ++recursion_count;
+            gCallback();
+            --recursion_count;
+        }
+    }
+
+    struct sigaction *old_action;
+    if (sig >= NUM_SIGNALS) {
+        /* This should never happen */
+        fprintf(stderr, "Unexpected signal %i\n", sig);
+        raise(SIGKILL);
+    }
+    old_action = &old_actions[sig];
+
+    if (old_action->sa_flags & SA_SIGINFO) {
+        // Handler is in sa_sigaction
+        old_action->sa_sigaction(sig, info, context);
+    } else {
+        if (old_action->sa_handler == SIG_DFL) {
+            fprintf(stderr, "taking default action for signal %i\n", sig);
+
+#if 1
+            struct sigaction dfl_action;
+            dfl_action.sa_handler = SIG_DFL;
+            sigemptyset (&dfl_action.sa_mask);
+            dfl_action.sa_flags = 0;
+            sigaction(sig, &dfl_action, NULL);
+
+            raise(sig);
+#else
+            raise(SIGKILL);
+#endif
+        } else if (old_action->sa_handler == SIG_IGN) {
+            /* ignore */
+        } else {
+            /* dispatch to handler */
+            old_action->sa_handler(sig);
+        }
+    }
+}
+
+void
+SetExceptionCallback(void (*callback)(void))
+{
+    assert(!gCallback);
+    if (!gCallback) {
+        gCallback = callback;
+
+        struct sigaction new_action;
+        new_action.sa_sigaction = signal_handler;
+        sigemptyset(&new_action.sa_mask);
+        new_action.sa_flags = SA_SIGINFO | SA_RESTART;
+
+
+        for (int sig = 1; sig < NUM_SIGNALS; ++sig) {
+            // SIGKILL and SIGSTOP can't be handled
+            if (sig != SIGKILL && sig != SIGSTOP) {
+                if (sigaction(sig,  NULL, &old_actions[sig]) >= 0) {
+                    sigaction(sig,  &new_action, NULL);
+                }
+            }
+        }
+    }
+}
+
+void
+ResetExceptionCallback(void)
+{
+    gCallback = NULL;
+}
+
+} /* namespace OS */
+
diff --git a/common/os_win32.cpp b/common/os_win32.cpp
new file mode 100644 (file)
index 0000000..587503c
--- /dev/null
@@ -0,0 +1,175 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+#include <assert.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "os.hpp"
+
+
+namespace OS {
+
+
+/* 
+ * Trick from http://locklessinc.com/articles/pthreads_on_windows/
+ */
+static CRITICAL_SECTION
+CriticalSection = {
+    (PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0
+};
+
+
+void
+AcquireMutex(void)
+{
+    EnterCriticalSection(&CriticalSection); 
+}
+
+
+void
+ReleaseMutex(void)
+{
+    LeaveCriticalSection(&CriticalSection); 
+}
+
+
+bool
+GetProcessName(char *str, size_t size)
+{
+    char szProcessPath[PATH_MAX];
+    char *lpProcessName;
+    char *lpProcessExt;
+
+    GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
+
+    lpProcessName = strrchr(szProcessPath, '\\');
+    lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
+
+    lpProcessExt = strrchr(lpProcessName, '.');
+    if (lpProcessExt) {
+        *lpProcessExt = '\0';
+    }
+
+    strncpy(str, lpProcessName, size);
+
+    return true;
+}
+
+bool
+GetCurrentDir(char *str, size_t size)
+{
+    DWORD ret;
+    ret = GetCurrentDirectoryA(size, str);
+    str[size - 1] = 0;
+    return ret == 0 ? false : true;
+}
+
+void
+DebugMessage(const char *format, ...)
+{
+    char buf[4096];
+
+    va_list ap;
+    va_start(ap, format);
+    fflush(stdout);
+    vsnprintf(buf, sizeof buf, format, ap);
+    va_end(ap);
+
+    OutputDebugStringA(buf);
+
+    /*
+     * Also write the message to stderr, when a debugger is not present (to
+     * avoid duplicate messages in command line debuggers).
+     */
+#if _WIN32_WINNT > 0x0400
+    if (!IsDebuggerPresent()) {
+        fflush(stdout);
+        fputs(buf, stderr);
+        fflush(stderr);
+    }
+#endif
+}
+
+long long GetTime(void)
+{
+    static LARGE_INTEGER frequency;
+    LARGE_INTEGER counter;
+    if (!frequency.QuadPart)
+        QueryPerformanceFrequency(&frequency);
+    QueryPerformanceCounter(&counter);
+    return counter.QuadPart*1000000LL/frequency.QuadPart;
+}
+
+void
+Abort(void)
+{
+#ifndef NDEBUG
+    DebugBreak();
+#else
+    ExitProcess(0);
+#endif
+}
+
+
+static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter = NULL;
+static void (*gCallback)(void) = NULL;
+
+static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
+{
+    if (gCallback) {
+        gCallback();
+    }
+
+       if (prevExceptionFilter) {
+               return prevExceptionFilter(pExceptionInfo);
+    } else {
+               return EXCEPTION_CONTINUE_SEARCH;
+    }
+}
+
+void
+SetExceptionCallback(void (*callback)(void))
+{
+    assert(!gCallback);
+
+    if (!gCallback) {
+        gCallback = callback;
+
+        assert(!prevExceptionFilter);
+        prevExceptionFilter = SetUnhandledExceptionFilter(UnhandledExceptionFilter);
+    }
+}
+
+void
+ResetExceptionCallback(void)
+{
+    gCallback = NULL;
+}
+
+
+} /* namespace OS */
diff --git a/common/trace_file.cpp b/common/trace_file.cpp
new file mode 100644 (file)
index 0000000..f48c1aa
--- /dev/null
@@ -0,0 +1,180 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Zack Rusin
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "trace_file.hpp"
+
+#include "trace_snappyfile.hpp"
+
+#include <assert.h>
+#include <string.h>
+
+#include <zlib.h>
+
+#include "os.hpp"
+
+#include <iostream>
+
+using namespace Trace;
+
+
+File::File(const std::string &filename,
+           File::Mode mode)
+    : m_mode(mode),
+      m_isOpened(false)
+{
+    if (!filename.empty()) {
+        open(filename, m_mode);
+    }
+}
+
+File::~File()
+{
+    close();
+}
+
+
+void File::setCurrentOffset(const File::Offset &offset)
+{
+    assert(0);
+}
+
+bool File::isZLibCompressed(const std::string &filename)
+{
+    std::fstream stream(filename.c_str(),
+                        std::fstream::binary | std::fstream::in);
+    if (!stream.is_open())
+        return false;
+
+    unsigned char byte1, byte2;
+    stream >> byte1;
+    stream >> byte2;
+    stream.close();
+
+    return (byte1 == 0x1f && byte2 == 0x8b);
+}
+
+
+bool File::isSnappyCompressed(const std::string &filename)
+{
+    std::fstream stream(filename.c_str(),
+                        std::fstream::binary | std::fstream::in);
+    if (!stream.is_open())
+        return false;
+
+    unsigned char byte1, byte2;
+    stream >> byte1;
+    stream >> byte2;
+    stream.close();
+
+    return (byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
+}
+
+typedef struct gz_stream {
+    z_stream stream;
+    int      z_err;   /* error code for last stream operation */
+    int      z_eof;   /* set if end of input file */
+    FILE     *file;   /* .gz file */
+} gz_dummy_stream;
+
+ZLibFile::ZLibFile(const std::string &filename,
+                   File::Mode mode)
+    : File(filename, mode),
+      m_gzFile(NULL)
+{
+}
+
+ZLibFile::~ZLibFile()
+{
+}
+
+bool ZLibFile::rawOpen(const std::string &filename, File::Mode mode)
+{
+    m_gzFile = gzopen(filename.c_str(),
+                      (mode == File::Write) ? "wb" : "rb");
+
+    if (mode == File::Read && m_gzFile) {
+        //XXX: unfortunately zlib doesn't support
+        //     SEEK_END or we could've done:
+        //m_endOffset = gzseek(m_gzFile, 0, SEEK_END);
+        //gzrewind(m_gzFile);
+        gz_dummy_stream *stream = (gz_dummy_stream *)m_gzFile;
+        long loc = ftell(stream->file);
+        fseek(stream->file,0,SEEK_END);
+        m_endOffset = ftell(stream->file);
+        fseek(stream->file, loc, SEEK_SET);
+    }
+
+    return m_gzFile != NULL;
+}
+
+bool ZLibFile::rawWrite(const void *buffer, size_t length)
+{
+    return gzwrite(m_gzFile, buffer, length) != -1;
+}
+
+bool ZLibFile::rawRead(void *buffer, size_t length)
+{
+    return gzread(m_gzFile, buffer, length) != -1;
+}
+
+int ZLibFile::rawGetc()
+{
+    return gzgetc(m_gzFile);
+}
+
+void ZLibFile::rawClose()
+{
+    if (m_gzFile) {
+        gzclose(m_gzFile);
+        m_gzFile = NULL;
+    }
+}
+
+void ZLibFile::rawFlush()
+{
+    gzflush(m_gzFile, Z_SYNC_FLUSH);
+}
+
+File::Offset ZLibFile::currentOffset()
+{
+    return File::Offset(gztell(m_gzFile));
+}
+
+bool ZLibFile::supportsOffsets() const
+{
+    return false;
+}
+
+bool ZLibFile::rawSkip(size_t)
+{
+    return false;
+}
+
+int ZLibFile::rawPercentRead()
+{
+    gz_dummy_stream *stream = (gz_dummy_stream *)m_gzFile;
+    return 100 * (ftell(stream->file) / m_endOffset);
+}
diff --git a/common/trace_file.hpp b/common/trace_file.hpp
new file mode 100644 (file)
index 0000000..4b1b70d
--- /dev/null
@@ -0,0 +1,224 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Zack Rusin
+ * 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 TRACE_FILE_HPP
+#define TRACE_FILE_HPP
+
+#include <string>
+#include <fstream>
+#include <stdint.h>
+
+namespace Trace {
+
+class File {
+public:
+    enum Mode {
+        Read,
+        Write
+    };
+    struct Offset {
+        Offset(uint64_t _chunk = 0, uint32_t _offsetInChunk = 0)
+            : chunk(_chunk),
+              offsetInChunk(_offsetInChunk)
+        {}
+        uint64_t chunk;
+        uint32_t offsetInChunk;
+    };
+
+public:
+    static bool isZLibCompressed(const std::string &filename);
+    static bool isSnappyCompressed(const std::string &filename);
+public:
+    File(const std::string &filename = std::string(),
+         File::Mode mode = File::Read);
+    virtual ~File();
+
+    bool isOpened() const;
+    File::Mode mode() const;
+
+    bool open(const std::string &filename, File::Mode mode);
+    bool write(const void *buffer, size_t length);
+    bool read(void *buffer, size_t length);
+    void close();
+    void flush(void);
+    int getc();
+    bool skip(size_t length);
+    int percentRead();
+
+    virtual bool supportsOffsets() const = 0;
+    virtual File::Offset currentOffset() = 0;
+    virtual void setCurrentOffset(const File::Offset &offset);
+protected:
+    virtual bool rawOpen(const std::string &filename, File::Mode mode) = 0;
+    virtual bool rawWrite(const void *buffer, size_t length) = 0;
+    virtual bool rawRead(void *buffer, size_t length) = 0;
+    virtual int rawGetc() = 0;
+    virtual void rawClose() = 0;
+    virtual void rawFlush() = 0;
+    virtual bool rawSkip(size_t length) = 0;
+    virtual int rawPercentRead() = 0;
+
+protected:
+    File::Mode m_mode;
+    bool m_isOpened;
+};
+
+inline bool File::isOpened() const
+{
+    return m_isOpened;
+}
+
+inline File::Mode File::mode() const
+{
+    return m_mode;
+}
+
+inline bool File::open(const std::string &filename, File::Mode mode)
+{
+    if (m_isOpened) {
+        close();
+    }
+    m_isOpened = rawOpen(filename, mode);
+    m_mode = mode;
+
+    return m_isOpened;
+}
+
+inline bool File::write(const void *buffer, size_t length)
+{
+    if (!m_isOpened || m_mode != File::Write) {
+        return false;
+    }
+    return rawWrite(buffer, length);
+}
+
+inline bool File::read(void *buffer, size_t length)
+{
+    if (!m_isOpened || m_mode != File::Read) {
+        return false;
+    }
+    return rawRead(buffer, length);
+}
+
+inline int File::percentRead()
+{
+    if (!m_isOpened || m_mode != File::Read) {
+        return 0;
+    }
+    return rawPercentRead();
+}
+
+inline void File::close()
+{
+    if (m_isOpened) {
+        rawClose();
+        m_isOpened = false;
+    }
+}
+
+inline void File::flush(void)
+{
+    if (m_mode == File::Write) {
+        rawFlush();
+    }
+}
+
+inline int File::getc()
+{
+    if (!m_isOpened || m_mode != File::Read) {
+        return -1;
+    }
+    return rawGetc();
+}
+
+inline bool File::skip(size_t length)
+{
+    if (!m_isOpened || m_mode != File::Read) {
+        return false;
+    }
+    return rawSkip(length);
+}
+
+class ZLibFile : public File {
+public:
+    ZLibFile(const std::string &filename = std::string(),
+             File::Mode mode = File::Read);
+    virtual ~ZLibFile();
+
+
+    virtual bool supportsOffsets() const;
+    virtual File::Offset currentOffset();
+protected:
+    virtual bool rawOpen(const std::string &filename, File::Mode mode);
+    virtual bool rawWrite(const void *buffer, size_t length);
+    virtual bool rawRead(void *buffer, size_t length);
+    virtual int rawGetc();
+    virtual void rawClose();
+    virtual void rawFlush();
+    virtual bool rawSkip(size_t length);
+    virtual int  rawPercentRead();
+private:
+    void *m_gzFile;
+    double m_endOffset;
+};
+
+inline bool
+operator<(const File::Offset &one, const File::Offset &two)
+{
+    return one.chunk < two.chunk ||
+            (one.chunk == two.chunk && one.offsetInChunk < two.offsetInChunk);
+}
+
+inline bool
+operator==(const File::Offset &one, const File::Offset &two)
+{
+    return one.chunk == two.chunk &&
+            one.offsetInChunk == two.offsetInChunk;
+}
+
+inline bool
+operator>=(const File::Offset &one, const File::Offset &two)
+{
+    return one.chunk > two.chunk ||
+            (one.chunk == two.chunk && one.offsetInChunk >= two.offsetInChunk);
+}
+
+inline bool
+operator>(const File::Offset &one, const File::Offset &two)
+{
+    return two < one;
+}
+
+inline bool
+operator<=(const File::Offset &one, const File::Offset &two)
+{
+    return two >= one;
+}
+
+
+}
+
+#endif
diff --git a/common/trace_format.hpp b/common/trace_format.hpp
new file mode 100644 (file)
index 0000000..a8ee5eb
--- /dev/null
@@ -0,0 +1,109 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Trace binary format.
+ *
+ * Grammar:
+ *
+ *   trace = event* EOF
+ *
+ *   event = EVENT_ENTER call_sig call_detail+
+ *         | EVENT_LEAVE call_no call_detail+
+ *
+ *   call_sig = sig_id ( name arg_names )?
+ *
+ *   call_detail = ARG index value
+ *               | RET value
+ *               | END
+ *
+ *   value = NULL
+ *         | FALSE
+ *         | TRUE
+ *         | SINT int
+ *         | UINT int
+ *         | FLOAT float
+ *         | DOUBLE double
+ *         | STRING string
+ *         | BLOB string
+ *         | ENUM enum_sig
+ *         | BITMASK bitmask_sig value
+ *         | ARRAY length value+
+ *         | STRUCT struct_sig value+
+ *         | OPAQUE int
+ *
+ *   call_sig = id name arg_name*
+ *            | id
+ *
+ *   enum_sig = id name value
+ *            | id
+ *
+ *   bitmask_sig = id count (name value)+
+ *               | id
+ *
+ *   string = length (BYTE)*
+ *
+ */
+
+#ifndef _TRACE_FORMAT_HPP_
+#define _TRACE_FORMAT_HPP_
+
+namespace Trace {
+
+#define TRACE_VERSION 1
+
+enum Event {
+    EVENT_ENTER = 0,
+    EVENT_LEAVE,
+};
+
+enum CallDetail {
+    CALL_END = 0,
+    CALL_ARG,
+    CALL_RET,
+    CALL_THREAD,
+};
+
+enum Type {
+    TYPE_NULL = 0,
+    TYPE_FALSE,
+    TYPE_TRUE,
+    TYPE_SINT,
+    TYPE_UINT,
+    TYPE_FLOAT,
+    TYPE_DOUBLE,
+    TYPE_STRING, // Null terminated, human readible string
+    TYPE_BLOB, // Block of bytes
+    TYPE_ENUM,
+    TYPE_BITMASK,
+    TYPE_ARRAY,
+    TYPE_STRUCT,
+    TYPE_OPAQUE,
+};
+
+
+} /* namespace Trace */
+
+#endif /* _TRACE_FORMAT_HPP_ */
diff --git a/common/trace_loader.cpp b/common/trace_loader.cpp
new file mode 100644 (file)
index 0000000..c14d815
--- /dev/null
@@ -0,0 +1,139 @@
+#include "trace_loader.hpp"
+
+
+using namespace Trace;
+
+Loader::Loader()
+    : m_frameMarker(FrameMarker_SwapBuffers)
+{
+}
+
+Loader::~Loader()
+{
+    close();
+}
+
+Loader::FrameMarker Loader::frameMarker() const
+{
+    return m_frameMarker;
+}
+
+void Loader::setFrameMarker(Loader::FrameMarker marker)
+{
+    m_frameMarker = marker;
+}
+
+int Loader::numberOfFrames() const
+{
+    return m_frameBookmarks.size();
+}
+
+int Loader::numberOfCallsInFrame(int frameIdx) const
+{
+    if (frameIdx > m_frameBookmarks.size()) {
+        return 0;
+    }
+    FrameBookmarks::const_iterator itr =
+        m_frameBookmarks.find(frameIdx);
+    return itr->second.numberOfCalls;
+}
+
+bool Loader::open(const char *filename)
+{
+    if (!m_parser.open(filename)) {
+        std::cerr << "error: failed to open " << filename << "\n";
+        return false;
+    }
+    if (!m_parser.supportsOffsets()) {
+        std::cerr << "error: " <<filename<< " doesn't support seeking "
+                  << "\n";
+        return false;
+    }
+
+    Trace::Call *call;
+    ParseBookmark startBookmark;
+    int numOfFrames = 0;
+    int numOfCalls = 0;
+    int lastPercentReport = 0;
+
+    m_parser.getBookmark(startBookmark);
+
+    while ((call = m_parser.scan_call())) {
+        ++numOfCalls;
+
+        if (isCallAFrameMarker(call)) {
+            FrameBookmark frameBookmark(startBookmark);
+            frameBookmark.numberOfCalls = numOfCalls;
+
+            m_frameBookmarks[numOfFrames] = frameBookmark;
+            ++numOfFrames;
+
+            if (m_parser.percentRead() - lastPercentReport >= 5) {
+                std::cerr << "\tPercent scanned = "
+                          << m_parser.percentRead()
+                          << "..."<<std::endl;
+                lastPercentReport = m_parser.percentRead();
+            }
+            
+            m_parser.getBookmark(startBookmark);
+            numOfCalls = 0;
+        }
+        //call->dump(std::cout, color);
+        delete call;
+    }
+    return true;
+}
+
+void Loader::close()
+{
+    m_parser.close();
+}
+
+bool Loader::isCallAFrameMarker(const Trace::Call *call) const
+{
+    std::string name = call->name();
+
+    switch (m_frameMarker) {
+    case FrameMarker_SwapBuffers:
+        return  name.find("SwapBuffers") != std::string::npos ||
+                name == "CGLFlushDrawable" ||
+                name == "glFrameTerminatorGREMEDY";
+        break;
+    case FrameMarker_Flush:
+        return name == "glFlush";
+        break;
+    case FrameMarker_Finish:
+        return name == "glFinish";
+        break;
+    case FrameMarker_Clear:
+        return name == "glClear";
+        break;
+    }
+    return false;
+}
+
+std::vector<Trace::Call *> Loader::frame(int idx)
+{
+    int numOfCalls = numberOfCallsInFrame(idx);
+    if (numOfCalls) {
+        const FrameBookmark &frameBookmark = m_frameBookmarks[idx];
+        std::vector<Trace::Call*> calls(numOfCalls);
+        m_parser.setBookmark(frameBookmark.start);
+
+        Trace::Call *call;
+        int parsedCalls = 0;
+        while ((call = m_parser.parse_call())) {
+
+            calls[parsedCalls] = call;
+            ++parsedCalls;
+
+            if (isCallAFrameMarker(call)) {
+                break;
+            }
+
+        }
+        assert(parsedCalls == numOfCalls);
+        return calls;
+    }
+    return std::vector<Trace::Call*>();
+}
diff --git a/common/trace_loader.hpp b/common/trace_loader.hpp
new file mode 100644 (file)
index 0000000..9f74a9b
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef TRACE_LOADER_HPP
+#define TRACE_LOADER_HPP
+
+#include "trace_file.hpp"
+#include "trace_parser.hpp"
+
+#include <string>
+#include <map>
+#include <queue>
+#include <vector>
+
+namespace Trace  {
+
+class Frame;
+
+class Loader
+{
+public:
+    enum FrameMarker {
+        FrameMarker_SwapBuffers,
+        FrameMarker_Flush,
+        FrameMarker_Finish,
+        FrameMarker_Clear
+    };
+public:
+    Loader();
+    ~Loader();
+
+    Loader::FrameMarker frameMarker() const;
+    void setFrameMarker(Loader::FrameMarker marker);
+
+    int numberOfFrames() const;
+    int numberOfCallsInFrame(int frameIdx) const;
+
+    bool open(const char *filename);
+    void close();
+
+    std::vector<Trace::Call*> frame(int idx);
+
+private:
+    struct FrameBookmark {
+        FrameBookmark()
+            : numberOfCalls(0)
+        {}
+        FrameBookmark(const ParseBookmark &s)
+            : start(s),
+              numberOfCalls(0)
+        {}
+
+        ParseBookmark start;
+        int numberOfCalls;
+    };
+    bool isCallAFrameMarker(const Trace::Call *call) const;
+
+private:
+    Trace::Parser m_parser;
+    FrameMarker m_frameMarker;
+
+    typedef std::map<int, FrameBookmark> FrameBookmarks;
+    FrameBookmarks m_frameBookmarks;
+};
+
+}
+
+#endif // TRACE_LOADER_HPP
diff --git a/common/trace_local_writer.cpp b/common/trace_local_writer.cpp
new file mode 100644 (file)
index 0000000..ea6c111
--- /dev/null
@@ -0,0 +1,156 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2011 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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "os.hpp"
+#include "trace_file.hpp"
+#include "trace_writer.hpp"
+#include "trace_format.hpp"
+
+
+namespace Trace {
+
+
+static void exceptionCallback(void)
+{
+    OS::DebugMessage("apitrace: flushing trace due to an exception\n");
+    localWriter.flush();
+}
+
+
+LocalWriter::LocalWriter() :
+    acquired(0)
+{}
+
+LocalWriter::~LocalWriter()
+{
+    OS::ResetExceptionCallback();
+}
+
+void
+LocalWriter::open(void) {
+
+    static unsigned dwCounter = 0;
+
+    const char *szExtension = "trace";
+    char szFileName[PATH_MAX];
+    const char *lpFileName;
+
+    lpFileName = getenv("TRACE_FILE");
+    if (lpFileName) {
+        strncpy(szFileName, lpFileName, PATH_MAX);
+    }
+    else {
+        char szProcessName[PATH_MAX];
+        char szCurrentDir[PATH_MAX];
+        OS::GetProcessName(szProcessName, PATH_MAX);
+        OS::GetCurrentDir(szCurrentDir, PATH_MAX);
+
+        for (;;) {
+            FILE *file;
+
+            if (dwCounter)
+                snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
+            else
+                snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
+
+            file = fopen(szFileName, "rb");
+            if (file == NULL)
+                break;
+
+            fclose(file);
+
+            ++dwCounter;
+        }
+    }
+
+    OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
+
+    Writer::open(szFileName);
+
+    OS::SetExceptionCallback(exceptionCallback);
+
+#if 0
+    // For debugging the exception handler
+    *((int *)0) = 0;
+#endif
+}
+
+unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
+    OS::AcquireMutex();
+    ++acquired;
+
+    if (!m_file->isOpened()) {
+        open();
+    }
+
+    return Writer::beginEnter(sig);
+}
+
+void LocalWriter::endEnter(void) {
+    Writer::endEnter();
+    --acquired;
+    OS::ReleaseMutex();
+}
+
+void LocalWriter::beginLeave(unsigned call) {
+    OS::AcquireMutex();
+    ++acquired;
+    Writer::beginLeave(call);
+}
+
+void LocalWriter::endLeave(void) {
+    Writer::endLeave();
+    --acquired;
+    OS::ReleaseMutex();
+}
+
+void LocalWriter::flush(void) {
+    /*
+     * Do nothing if the mutex is already acquired (e.g., if a segfault happen
+     * while writing the file) to prevent dead-lock.
+     */
+
+    if (!acquired) {
+        OS::AcquireMutex();
+        if (m_file->isOpened()) {
+            m_file->flush();
+        }
+        OS::ReleaseMutex();
+    }
+}
+
+
+LocalWriter localWriter;
+
+
+} /* namespace Trace */
+
diff --git a/common/trace_model.cpp b/common/trace_model.cpp
new file mode 100644 (file)
index 0000000..306b9e7
--- /dev/null
@@ -0,0 +1,379 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "formatter.hpp"
+#include "trace_model.hpp"
+
+
+namespace Trace {
+
+
+Call::~Call() {
+    for (unsigned i = 0; i < args.size(); ++i) {
+        delete args[i];
+    }
+
+    if (ret) {
+        delete ret;
+    }
+}
+
+
+String::~String() {
+    delete [] value;
+}
+
+
+Struct::~Struct() {
+    for (std::vector<Value *>::iterator it = members.begin(); it != members.end(); ++it) {
+        delete *it;
+    }
+}
+
+
+Array::~Array() {
+    for (std::vector<Value *>::iterator it = values.begin(); it != values.end(); ++it) {
+        delete *it;
+    }
+}
+
+Blob::~Blob() {
+    // Blobs are often bound and referred during many calls, so we can't delete
+    // them here in that case.
+    //
+    // Once bound there is no way to know when they were unbound, which
+    // effectively means we have to leak them.  A better solution would be to
+    // keep a list of bound pointers, and defer the destruction to when the
+    // trace in question has been fully processed.
+    if (!bound) {
+        delete [] buf;
+    }
+}
+
+
+// bool cast
+bool Null   ::toBool(void) const { return false; }
+bool Bool   ::toBool(void) const { return value; }
+bool SInt   ::toBool(void) const { return value != 0; }
+bool UInt   ::toBool(void) const { return value != 0; }
+bool Float  ::toBool(void) const { return value != 0; }
+bool String ::toBool(void) const { return true; }
+bool Enum   ::toBool(void) const { return sig->value != 0; }
+bool Struct ::toBool(void) const { return true; }
+bool Array  ::toBool(void) const { return true; }
+bool Blob   ::toBool(void) const { return true; }
+bool Pointer::toBool(void) const { return value != 0; }
+
+
+// signed integer cast
+signed long long Value  ::toSInt(void) const { assert(0); return 0; }
+signed long long Null   ::toSInt(void) const { return 0; }
+signed long long Bool   ::toSInt(void) const { return static_cast<signed long long>(value); }
+signed long long SInt   ::toSInt(void) const { return value; }
+signed long long UInt   ::toSInt(void) const { assert(static_cast<signed long long>(value) >= 0); return static_cast<signed long long>(value); }
+signed long long Float  ::toSInt(void) const { return static_cast<signed long long>(value); }
+signed long long Enum   ::toSInt(void) const { return sig->value; }
+
+
+// unsigned integer cast
+unsigned long long Value  ::toUInt(void) const { assert(0); return 0; }
+unsigned long long Null   ::toUInt(void) const { return 0; }
+unsigned long long Bool   ::toUInt(void) const { return static_cast<unsigned long long>(value); }
+unsigned long long SInt   ::toUInt(void) const { assert(value >= 0); return static_cast<signed long long>(value); }
+unsigned long long UInt   ::toUInt(void) const { return value; }
+unsigned long long Float  ::toUInt(void) const { return static_cast<unsigned long long>(value); }
+unsigned long long Enum   ::toUInt(void) const { assert(sig->value >= 0); return sig->value; }
+
+
+// floating point cast
+float Value  ::toFloat(void) const { assert(0); return 0; }
+float Null   ::toFloat(void) const { return 0; }
+float Bool   ::toFloat(void) const { return static_cast<float>(value); }
+float SInt   ::toFloat(void) const { return static_cast<float>(value); }
+float UInt   ::toFloat(void) const { return static_cast<float>(value); }
+float Float  ::toFloat(void) const { return value; }
+float Enum   ::toFloat(void) const { return static_cast<float>(sig->value); }
+
+
+// floating point cast
+double Value  ::toDouble(void) const { assert(0); return 0; }
+double Null   ::toDouble(void) const { return 0; }
+double Bool   ::toDouble(void) const { return static_cast<double>(value); }
+double SInt   ::toDouble(void) const { return static_cast<double>(value); }
+double UInt   ::toDouble(void) const { return static_cast<double>(value); }
+double Float  ::toDouble(void) const { return value; }
+double Enum   ::toDouble(void) const { return static_cast<double>(sig->value); }
+
+
+// pointer cast
+void * Value  ::toPointer(void) const { assert(0); return NULL; }
+void * Null   ::toPointer(void) const { return NULL; }
+void * Blob   ::toPointer(void) const { return buf; }
+void * Pointer::toPointer(void) const { return (void *)value; }
+
+void * Value  ::toPointer(bool bind) { assert(0); return NULL; }
+void * Null   ::toPointer(bool bind) { return NULL; }
+void * Blob   ::toPointer(bool bind) { if (bind) bound = true; return buf; }
+void * Pointer::toPointer(bool bind) { return (void *)value; }
+
+
+// pointer cast
+unsigned long long Value  ::toUIntPtr(void) const { assert(0); return 0; }
+unsigned long long Null   ::toUIntPtr(void) const { return 0; }
+unsigned long long Pointer::toUIntPtr(void) const { return value; }
+
+
+// string cast
+const char * Value ::toString(void) const { assert(0); return NULL; }
+const char * Null  ::toString(void) const { return NULL; }
+const char * String::toString(void) const { return value; }
+
+
+// virtual Value::visit()
+void Null   ::visit(Visitor &visitor) { visitor.visit(this); }
+void Bool   ::visit(Visitor &visitor) { visitor.visit(this); }
+void SInt   ::visit(Visitor &visitor) { visitor.visit(this); }
+void UInt   ::visit(Visitor &visitor) { visitor.visit(this); }
+void Float  ::visit(Visitor &visitor) { visitor.visit(this); }
+void String ::visit(Visitor &visitor) { visitor.visit(this); }
+void Enum   ::visit(Visitor &visitor) { visitor.visit(this); }
+void Bitmask::visit(Visitor &visitor) { visitor.visit(this); }
+void Struct ::visit(Visitor &visitor) { visitor.visit(this); }
+void Array  ::visit(Visitor &visitor) { visitor.visit(this); }
+void Blob   ::visit(Visitor &visitor) { visitor.visit(this); }
+void Pointer::visit(Visitor &visitor) { visitor.visit(this); }
+
+
+void Visitor::visit(Null *) { assert(0); }
+void Visitor::visit(Bool *) { assert(0); }
+void Visitor::visit(SInt *) { assert(0); }
+void Visitor::visit(UInt *) { assert(0); }
+void Visitor::visit(Float *) { assert(0); }
+void Visitor::visit(String *) { assert(0); }
+void Visitor::visit(Enum *node) { assert(0); }
+void Visitor::visit(Bitmask *node) { visit(static_cast<UInt *>(node)); }
+void Visitor::visit(Struct *) { assert(0); }
+void Visitor::visit(Array *) { assert(0); }
+void Visitor::visit(Blob *) { assert(0); }
+void Visitor::visit(Pointer *) { assert(0); }
+
+
+class Dumper : public Visitor
+{
+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;
+
+public:
+    Dumper(std::ostream &_os, bool color) : os(_os) {
+        formatter = Formatter::defaultFormatter(color);
+        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() {
+        delete normal;
+        delete bold;
+        delete italic;
+        delete red;
+        delete pointer;
+        delete literal;
+        delete formatter;
+    }
+
+    void visit(Null *) {
+        os << "NULL";
+    }
+
+    void visit(Bool *node) {
+        os << literal << (node->value ? "true" : "false") << normal;
+    }
+
+    void visit(SInt *node) {
+        os << literal << node->value << normal;
+    }
+
+    void visit(UInt *node) {
+        os << literal << node->value << normal;
+    }
+
+    void visit(Float *node) {
+        os << literal << node->value << normal;
+    }
+
+    void visit(String *node) {
+        os << literal << "\"";
+        for (const char *it = node->value; *it; ++it) {
+            unsigned char c = (unsigned char) *it;
+            if (c == '\"')
+                os << "\\\"";
+            else if (c == '\\')
+                os << "\\\\";
+            else if (c >= 0x20 && c <= 0x7e)
+                os << c;
+            else if (c == '\t') {
+                os << "\t";
+            } else if (c == '\r') {
+                // Ignore carriage-return
+            } else if (c == '\n') {
+                // Reset formatting so that it looks correct with 'less -R'
+                os << normal << '\n' << literal;
+            } else {
+                unsigned octal0 = c & 0x7;
+                unsigned octal1 = (c >> 3) & 0x7;
+                unsigned octal2 = (c >> 3) & 0x7;
+                os << "\\";
+                if (octal2)
+                    os << octal2;
+                if (octal1)
+                    os << octal1;
+                os << octal0;
+            }
+        }
+        os << "\"" << normal;
+    }
+
+    void visit(Enum *node) {
+        os << literal << node->sig->name << normal;
+    }
+
+    void visit(Bitmask *bitmask) {
+        unsigned long long value = bitmask->value;
+        const BitmaskSig *sig = bitmask->sig;
+        bool first = true;
+        for (const BitmaskFlag *it = sig->flags; value != 0 && it != sig->flags + sig->num_flags; ++it) {
+            if ((it->value && (value & it->value) == it->value) ||
+                (!it->value && value == 0)) {
+                if (!first) {
+                    os << " | ";
+                }
+                os << literal << it->name << normal;
+                value &= ~it->value;
+                first = false;
+            }
+        }
+        if (value || first) {
+            if (!first) {
+                os << " | ";
+            }
+            os << literal << "0x" << std::hex << value << std::dec << normal;
+        }
+    }
+
+    void visit(Struct *s) {
+        const char *sep = "";
+        os << "{";
+        for (unsigned i = 0; i < s->members.size(); ++i) {
+            os << sep << italic << s->sig->member_names[i] << normal << " = ";
+            _visit(s->members[i]);
+            sep = ", ";
+        }
+        os << "}";
+    }
+
+    void visit(Array *array) {
+        if (array->values.size() == 1) {
+            os << "&";
+            _visit(array->values[0]);
+        }
+        else {
+            const char *sep = "";
+            os << "{";
+            for (std::vector<Value *>::iterator it = array->values.begin(); it != array->values.end(); ++it) {
+                os << sep;
+                _visit(*it);
+                sep = ", ";
+            }
+            os << "}";
+        }
+    }
+
+    void visit(Blob *blob) {
+        os << pointer << "blob(" << blob->size << ")" << normal;
+    }
+
+    void visit(Pointer *p) {
+        os << pointer << "0x" << std::hex << p->value << std::dec << normal;
+    }
+
+    void visit(Call *call) {
+        const char *sep = "";
+        os << bold << call->sig->name << normal << "(";
+        for (unsigned i = 0; i < call->args.size(); ++i) {
+            os << sep << italic << call->sig->arg_names[i] << normal << " = ";
+            if (call->args[i]) {
+                _visit(call->args[i]);
+            } else {
+               os << "?";
+            }
+            sep = ", ";
+        }
+        os << ")";
+        if (call->ret) {
+            os << " = ";
+            _visit(call->ret);
+        }
+        os << "\n";
+    }
+};
+
+
+void Value::dump(std::ostream &os, bool color) {
+    Dumper d(os, color);
+    visit(d);
+}
+
+
+static Null null;
+
+const Value & Value::operator[](size_t index) const {
+    const Array *array = dynamic_cast<const Array *>(this);
+    if (array) {
+        if (index < array->values.size()) {
+            return *array->values[index];
+        }
+    }
+    return null;
+}
+
+void Call::dump(std::ostream &os, bool color) {
+    Dumper d(os, color);
+    os << no << " ";
+    d.visit(this);
+}
+
+
+} /* namespace Trace */
diff --git a/common/trace_model.hpp b/common/trace_model.hpp
new file mode 100644 (file)
index 0000000..a74508e
--- /dev/null
@@ -0,0 +1,357 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Object hierarchy for describing the traces in memory.
+ */
+
+#ifndef _TRACE_MODEL_HPP_
+#define _TRACE_MODEL_HPP_
+
+
+#include <assert.h>
+
+#include <map>
+#include <vector>
+#include <iostream>
+
+
+namespace Trace {
+
+
+typedef unsigned Id;
+
+
+struct FunctionSig {
+    Id id;
+    const char *name;
+    unsigned num_args;
+    const char **arg_names;
+};
+
+
+struct StructSig {
+    Id id;
+    const char *name;
+    unsigned num_members;
+    const char **member_names;
+};
+
+
+struct EnumSig {
+    Id id;
+    const char *name;
+    signed long long value;
+};
+
+
+struct BitmaskFlag {
+    const char *name;
+    unsigned long long value;
+};
+
+
+struct BitmaskSig {
+    Id id;
+    unsigned num_flags;
+    const BitmaskFlag *flags;
+};
+
+
+class Visitor;
+
+
+class Value
+{
+public:
+    virtual ~Value() {}
+    virtual void visit(Visitor &visitor) = 0;
+
+    virtual bool toBool(void) const = 0;
+    virtual signed long long toSInt(void) const;
+    virtual unsigned long long toUInt(void) const;
+    virtual float toFloat(void) const;
+    virtual double toDouble(void) const;
+
+    virtual void *toPointer(void) const;
+    virtual void *toPointer(bool bind);
+    virtual unsigned long long toUIntPtr(void) const;
+    virtual const char *toString(void) const;
+
+    const Value & operator[](size_t index) const;
+
+    void dump(std::ostream &os, bool color=true);
+};
+
+
+class Null : public Value
+{
+public:
+    bool toBool(void) const;
+    signed long long toSInt(void) const;
+    unsigned long long toUInt(void) const;
+    virtual float toFloat(void) const;
+    virtual double toDouble(void) const;
+    void *toPointer(void) const;
+    void *toPointer(bool bind);
+    unsigned long long toUIntPtr(void) const;
+    const char *toString(void) const;
+    void visit(Visitor &visitor);
+};
+
+
+class Bool : public Value
+{
+public:
+    Bool(bool _value) : value(_value) {}
+
+    bool toBool(void) const;
+    signed long long toSInt(void) const;
+    unsigned long long toUInt(void) const;
+    virtual float toFloat(void) const;
+    virtual double toDouble(void) const;
+    void visit(Visitor &visitor);
+
+    bool value;
+};
+
+
+class SInt : public Value
+{
+public:
+    SInt(signed long long _value) : value(_value) {}
+
+    bool toBool(void) const;
+    signed long long toSInt(void) const;
+    unsigned long long toUInt(void) const;
+    virtual float toFloat(void) const;
+    virtual double toDouble(void) const;
+    void visit(Visitor &visitor);
+
+    signed long long value;
+};
+
+
+class UInt : public Value
+{
+public:
+    UInt(unsigned long long _value) : value(_value) {}
+
+    bool toBool(void) const;
+    signed long long toSInt(void) const;
+    unsigned long long toUInt(void) const;
+    virtual float toFloat(void) const;
+    virtual double toDouble(void) const;
+    void visit(Visitor &visitor);
+
+    unsigned long long value;
+};
+
+
+class Float : public Value
+{
+public:
+    Float(double _value) : value(_value) {}
+
+    bool toBool(void) const;
+    signed long long toSInt(void) const;
+    unsigned long long toUInt(void) const;
+    virtual float toFloat(void) const;
+    virtual double toDouble(void) const;
+    void visit(Visitor &visitor);
+
+    double value;
+};
+
+
+class String : public Value
+{
+public:
+    String(const char * _value) : value(_value) {}
+    ~String();
+
+    bool toBool(void) const;
+    const char *toString(void) const;
+    void visit(Visitor &visitor);
+
+    const char * value;
+};
+
+
+class Enum : public Value
+{
+public:
+    Enum(const EnumSig *_sig) : sig(_sig) {}
+
+    bool toBool(void) const;
+    signed long long toSInt(void) const;
+    unsigned long long toUInt(void) const;
+    virtual float toFloat(void) const;
+    virtual double toDouble(void) const;
+    void visit(Visitor &visitor);
+
+    const EnumSig *sig;
+};
+
+
+class Bitmask : public UInt
+{
+public:
+    Bitmask(const BitmaskSig *_sig, unsigned long long _value) : UInt(_value), sig(_sig) {}
+
+    void visit(Visitor &visitor);
+
+    const BitmaskSig *sig;
+};
+
+
+class Struct : public Value
+{
+public:
+    Struct(StructSig *_sig) : sig(_sig), members(_sig->num_members) { }
+    ~Struct();
+
+    bool toBool(void) const;
+    void visit(Visitor &visitor);
+
+    const StructSig *sig;
+    std::vector<Value *> members;
+};
+
+
+class Array : public Value
+{
+public:
+    Array(size_t len) : values(len) {}
+    ~Array();
+
+    bool toBool(void) const;
+    void visit(Visitor &visitor);
+
+    std::vector<Value *> values;
+};
+
+
+class Blob : public Value
+{
+public:
+    Blob(size_t _size) {
+        size = _size;
+        buf = new char[_size];
+        bound = false;
+    }
+
+    ~Blob();
+
+    bool toBool(void) const;
+    void *toPointer(void) const;
+    void *toPointer(bool bind);
+    void visit(Visitor &visitor);
+
+    size_t size;
+    char *buf;
+    bool bound;
+};
+
+
+class Pointer : public UInt
+{
+public:
+    Pointer(unsigned long long value) : UInt(value) {}
+
+    bool toBool(void) const;
+    void *toPointer(void) const;
+    void *toPointer(bool bind);
+    unsigned long long toUIntPtr(void) const;
+    void visit(Visitor &visitor);
+};
+
+
+class Visitor
+{
+public:
+    virtual void visit(Null *);
+    virtual void visit(Bool *);
+    virtual void visit(SInt *);
+    virtual void visit(UInt *);
+    virtual void visit(Float *);
+    virtual void visit(String *);
+    virtual void visit(Enum *);
+    virtual void visit(Bitmask *);
+    virtual void visit(Struct *);
+    virtual void visit(Array *);
+    virtual void visit(Blob *);
+    virtual void visit(Pointer *);
+
+protected:
+    inline void _visit(Value *value) {
+        if (value) { 
+            value->visit(*this); 
+        }
+    }
+};
+
+
+inline std::ostream & operator <<(std::ostream &os, Value *value) {
+    if (value) {
+        value->dump(os);
+    }
+    return os;
+}
+
+
+class Call
+{
+public:
+    unsigned no;
+    const FunctionSig *sig;
+    std::vector<Value *> args;
+    Value *ret;
+
+    Call(FunctionSig *_sig) : sig(_sig), args(_sig->num_args), ret(0) { }
+    ~Call();
+
+    inline const char * name(void) const {
+        return sig->name;
+    }
+
+    inline Value & arg(unsigned index) {
+        assert(index < args.size());
+        return *(args[index]);
+    }
+
+    void dump(std::ostream &os, bool color=true);
+};
+
+
+inline std::ostream & operator <<(std::ostream &os, Call &call) {
+    call.dump(os);
+    return os;
+}
+
+
+} /* namespace Trace */
+
+#endif /* _TRACE_MODEL_HPP_ */
diff --git a/common/trace_model_writer.cpp b/common/trace_model_writer.cpp
new file mode 100644 (file)
index 0000000..dcfcf86
--- /dev/null
@@ -0,0 +1,127 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "trace_writer.hpp"
+
+
+namespace Trace {
+
+
+class ModelWriter : public Visitor
+{
+protected:
+    Writer &writer;
+
+public:
+    ModelWriter(Writer &_writer) :
+        writer(_writer) {
+    }
+
+    void visit(Null *) {
+        writer.writeNull();
+    }
+
+    void visit(Bool *node) {
+        writer.writeBool(node->value);
+    }
+
+    void visit(SInt *node) {
+        writer.writeSInt(node->value);
+    }
+
+    void visit(UInt *node) {
+        writer.writeUInt(node->value);
+    }
+
+    void visit(Float *node) {
+        writer.writeFloat(node->value);
+    }
+
+    void visit(String *node) {
+        writer.writeString(node->value);
+    }
+
+    void visit(Enum *node) {
+        writer.writeEnum(node->sig);
+    }
+
+    void visit(Bitmask *node) {
+        writer.writeBitmask(node->sig, node->value);
+    }
+
+    void visit(Struct *node) {
+        writer.beginStruct(node->sig);
+        for (unsigned i = 0; i < node->sig->num_members; ++i) {
+            _visit(node->members[i]);
+        }
+        writer.endStruct();
+    }
+
+    void visit(Array *node) {
+        writer.beginArray(node->values.size());
+        for (std::vector<Value *>::iterator it = node->values.begin(); it != node->values.end(); ++it) {
+            _visit(*it);
+        }
+        writer.endArray();
+    }
+
+    void visit(Blob *node) {
+        writer.writeBlob(node->buf, node->size);
+    }
+
+    void visit(Pointer *node) {
+        writer.writeOpaque((const void *) (size_t) node->value);
+    }
+
+    void visit(Call *call) {
+        unsigned call_no = writer.beginEnter(call->sig);
+        for (unsigned i = 0; i < call->args.size(); ++i) {
+            if (call->args[i]) {
+                writer.beginArg(i);
+                _visit(call->args[i]);
+                writer.endArg();
+            }
+        }
+        writer.endEnter();
+        writer.beginLeave(call_no);
+        if (call->ret) {
+            writer.beginReturn();
+            _visit(call->ret);
+            writer.endReturn();
+        }
+        writer.endLeave();
+    }
+};
+
+
+void Writer::writeCall(Call *call) {
+    ModelWriter visitor(*this);
+    visitor.visit(call);
+}
+
+
+} /* namespace Trace */
+
diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp
new file mode 100644 (file)
index 0000000..d7b20d2
--- /dev/null
@@ -0,0 +1,731 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "trace_file.hpp"
+#include "trace_snappyfile.hpp"
+#include "trace_parser.hpp"
+
+
+#define TRACE_VERBOSE 0
+
+
+namespace Trace {
+
+
+Parser::Parser() {
+    file = NULL;
+    next_call_no = 0;
+    version = 0;
+}
+
+
+Parser::~Parser() {
+    close();
+}
+
+
+bool Parser::open(const char *filename) {
+    assert(!file);
+    if (File::isZLibCompressed(filename)) {
+        file = new ZLibFile;
+    } else {
+        file = new SnappyFile;
+    }
+
+    if (!file->open(filename, File::Read)) {
+        return false;
+    }
+
+    version = read_uint();
+    if (version > TRACE_VERSION) {
+        std::cerr << "error: unsupported trace format version " << version << "\n";
+        return false;
+    }
+
+    return true;
+}
+
+template <typename Iter>
+inline void
+deleteAll(Iter begin, Iter end)
+{
+    while (begin != end) {
+        delete *begin;
+        ++begin;
+    }
+}
+
+template <typename Container>
+inline void
+deleteAll(Container &c)
+{
+    deleteAll(c.begin(), c.end());
+    c.clear();
+}
+
+void Parser::close(void) {
+    if (file) {
+        file->close();
+        delete file;
+        file = NULL;
+    }
+
+    deleteAll(calls);
+
+    // Delete all signature data.  Signatures are mere structures which don't
+    // own their own memory, so we need to destroy all data we created here.
+
+    for (FunctionMap::iterator it = functions.begin(); it != functions.end(); ++it) {
+        FunctionSigState *sig = *it;
+        if (sig) {
+            delete [] sig->name;
+            for (unsigned arg = 0; arg < sig->num_args; ++arg) {
+                delete [] sig->arg_names[arg];
+            }
+            delete [] sig->arg_names;
+            delete sig;
+        }
+    }
+    functions.clear();
+
+    for (StructMap::iterator it = structs.begin(); it != structs.end(); ++it) {
+        StructSigState *sig = *it;
+        if (sig) {
+            delete [] sig->name;
+            for (unsigned member = 0; member < sig->num_members; ++member) {
+                delete [] sig->member_names[member];
+            }
+            delete [] sig->member_names;
+            delete sig;
+        }
+    }
+    structs.clear();
+
+    for (EnumMap::iterator it = enums.begin(); it != enums.end(); ++it) {
+        EnumSigState *sig = *it;
+        if (sig) {
+            delete [] sig->name;
+            delete sig;
+        }
+    }
+    enums.clear();
+    
+    for (BitmaskMap::iterator it = bitmasks.begin(); it != bitmasks.end(); ++it) {
+        BitmaskSigState *sig = *it;
+        if (sig) {
+            for (unsigned flag = 0; flag < sig->num_flags; ++flag) {
+                delete [] sig->flags[flag].name;
+            }
+            delete [] sig->flags;
+            delete sig;
+        }
+    }
+    bitmasks.clear();
+}
+
+
+void Parser::getBookmark(ParseBookmark &bookmark) {
+    bookmark.offset = file->currentOffset();
+    bookmark.next_call_no = next_call_no;
+}
+
+
+void Parser::setBookmark(const ParseBookmark &bookmark) {
+    file->setCurrentOffset(bookmark.offset);
+    next_call_no = bookmark.next_call_no;
+    
+    // Simply ignore all pending calls
+    deleteAll(calls);
+}
+
+
+Call *Parser::parse_call(Mode mode) {
+    do {
+        int c = read_byte();
+        switch(c) {
+        case Trace::EVENT_ENTER:
+            parse_enter(mode);
+            break;
+        case Trace::EVENT_LEAVE:
+            return parse_leave(mode);
+        default:
+            std::cerr << "error: unknown event " << c << "\n";
+            exit(1);
+        case -1:
+            for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
+                std::cerr << "warning: incomplete call " << (*it)->name() << "\n";
+                std::cerr << **it << "\n";
+            }
+            return NULL;
+        }
+    } while(true);
+}
+
+
+/**
+ * Helper function to lookup an ID in a vector, resizing the vector if it doesn't fit.
+ */
+template<class T>
+T *lookup(std::vector<T *> &map, size_t index) {
+    if (index >= map.size()) {
+        map.resize(index + 1);
+        return NULL;
+    } else {
+        return map[index];
+    }
+}
+
+
+FunctionSig *Parser::parse_function_sig(void) {
+    size_t id = read_uint();
+
+    FunctionSigState *sig = lookup(functions, id);
+
+    if (!sig) {
+        /* parse the signature */
+        sig = new FunctionSigState;
+        sig->id = id;
+        sig->name = read_string();
+        sig->num_args = read_uint();
+        const char **arg_names = new const char *[sig->num_args];
+        for (unsigned i = 0; i < sig->num_args; ++i) {
+            arg_names[i] = read_string();
+        }
+        sig->arg_names = arg_names;
+        sig->offset = file->currentOffset();
+        functions[id] = sig;
+    } else if (file->currentOffset() < sig->offset) {
+        /* skip over the signature */
+        skip_string(); /* name */
+        int num_args = read_uint();
+        for (unsigned i = 0; i < num_args; ++i) {
+             skip_string(); /*arg_name*/
+        }
+    }
+
+    assert(sig);
+    return sig;
+}
+
+
+StructSig *Parser::parse_struct_sig() {
+    size_t id = read_uint();
+
+    StructSigState *sig = lookup(structs, id);
+
+    if (!sig) {
+        /* parse the signature */
+        sig = new StructSigState;
+        sig->id = id;
+        sig->name = read_string();
+        sig->num_members = read_uint();
+        const char **member_names = new const char *[sig->num_members];
+        for (unsigned i = 0; i < sig->num_members; ++i) {
+            member_names[i] = read_string();
+        }
+        sig->member_names = member_names;
+        sig->offset = file->currentOffset();
+        structs[id] = sig;
+    } else if (file->currentOffset() < sig->offset) {
+        /* skip over the signature */
+        skip_string(); /* name */
+        unsigned num_members = read_uint();
+        for (unsigned i = 0; i < num_members; ++i) {
+            skip_string(); /* member_name */
+        }
+    }
+
+    assert(sig);
+    return sig;
+}
+
+
+EnumSig *Parser::parse_enum_sig() {
+    size_t id = read_uint();
+
+    EnumSigState *sig = lookup(enums, id);
+
+    if (!sig) {
+        /* parse the signature */
+        sig = new EnumSigState;
+        sig->id = id;
+        sig->name = read_string();
+        Value *value = parse_value();
+        sig->value = value->toSInt();
+        delete value;
+        sig->offset = file->currentOffset();
+        enums[id] = sig;
+    } else if (file->currentOffset() < sig->offset) {
+        /* skip over the signature */
+        skip_string(); /*name*/
+        scan_value();
+    }
+
+    assert(sig);
+    return sig;
+}
+
+
+BitmaskSig *Parser::parse_bitmask_sig() {
+    size_t id = read_uint();
+
+    BitmaskSigState *sig = lookup(bitmasks, id);
+
+    if (!sig) {
+        /* parse the signature */
+        sig = new BitmaskSigState;
+        sig->id = id;
+        sig->num_flags = read_uint();
+        BitmaskFlag *flags = new BitmaskFlag[sig->num_flags];
+        for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) {
+            it->name = read_string();
+            it->value = read_uint();
+            if (it->value == 0 && it != flags) {
+                std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n";
+            }
+        }
+        sig->flags = flags;
+        sig->offset = file->currentOffset();
+        bitmasks[id] = sig;
+    } else if (file->currentOffset() < sig->offset) {
+        /* skip over the signature */
+        int num_flags = read_uint();
+        for (int i = 0; i < num_flags; ++i) {
+            skip_string(); /*name */
+            skip_uint(); /* value */
+        }
+    }
+
+    assert(sig);
+    return sig;
+}
+
+
+void Parser::parse_enter(Mode mode) {
+    FunctionSig *sig = parse_function_sig();
+
+    Call *call = new Call(sig);
+
+    call->no = next_call_no++;
+
+    if (parse_call_details(call, mode)) {
+        calls.push_back(call);
+    } else {
+        delete call;
+    }
+}
+
+
+Call *Parser::parse_leave(Mode mode) {
+    unsigned call_no = read_uint();
+    Call *call = NULL;
+    for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
+        if ((*it)->no == call_no) {
+            call = *it;
+            calls.erase(it);
+            break;
+        }
+    }
+    if (!call) {
+        return NULL;
+    }
+
+    if (parse_call_details(call, mode)) {
+        return call;
+    } else {
+        delete call;
+        return NULL;
+    }
+}
+
+
+bool Parser::parse_call_details(Call *call, Mode mode) {
+    do {
+        int c = read_byte();
+        switch(c) {
+        case Trace::CALL_END:
+            return true;
+        case Trace::CALL_ARG:
+            parse_arg(call, mode);
+            break;
+        case Trace::CALL_RET:
+            call->ret = parse_value(mode);
+            break;
+        default:
+            std::cerr << "error: ("<<call->name()<< ") unknown call detail "
+                      << c << "\n";
+            exit(1);
+        case -1:
+            return false;
+        }
+    } while(true);
+}
+
+
+void Parser::parse_arg(Call *call, Mode mode) {
+    unsigned index = read_uint();
+    Value *value = parse_value(mode);
+    if (value) {
+        if (index >= call->args.size()) {
+            call->args.resize(index + 1);
+        }
+        call->args[index] = value;
+    }
+}
+
+
+Value *Parser::parse_value(void) {
+    int c;
+    Value *value;
+    c = read_byte();
+    switch(c) {
+    case Trace::TYPE_NULL:
+        value = new Null;
+        break;
+    case Trace::TYPE_FALSE:
+        value = new Bool(false);
+        break;
+    case Trace::TYPE_TRUE:
+        value = new Bool(true);
+        break;
+    case Trace::TYPE_SINT:
+        value = parse_sint();
+        break;
+    case Trace::TYPE_UINT:
+        value = parse_uint();
+        break;
+    case Trace::TYPE_FLOAT:
+        value = parse_float();
+        break;
+    case Trace::TYPE_DOUBLE:
+        value = parse_double();
+        break;
+    case Trace::TYPE_STRING:
+        value = parse_string();
+        break;
+    case Trace::TYPE_ENUM:
+        value = parse_enum();
+        break;
+    case Trace::TYPE_BITMASK:
+        value = parse_bitmask();
+        break;
+    case Trace::TYPE_ARRAY:
+        value = parse_array();
+        break;
+    case Trace::TYPE_STRUCT:
+        value = parse_struct();
+        break;
+    case Trace::TYPE_BLOB:
+        value = parse_blob();
+        break;
+    case Trace::TYPE_OPAQUE:
+        value = parse_opaque();
+        break;
+    default:
+        std::cerr << "error: unknown type " << c << "\n";
+        exit(1);
+    case -1:
+        value = NULL;
+        break;
+    }
+#if TRACE_VERBOSE
+    if (value) {
+        std::cerr << "\tVALUE " << value << "\n";
+    }
+#endif
+    return value;
+}
+
+
+void Parser::scan_value(void) {
+    int c = read_byte();
+    switch(c) {
+    case Trace::TYPE_NULL:
+    case Trace::TYPE_FALSE:
+    case Trace::TYPE_TRUE:
+        break;
+    case Trace::TYPE_SINT:
+        scan_sint();
+        break;
+    case Trace::TYPE_UINT:
+        scan_uint();
+        break;
+    case Trace::TYPE_FLOAT:
+        scan_float();
+        break;
+    case Trace::TYPE_DOUBLE:
+        scan_double();
+        break;
+    case Trace::TYPE_STRING:
+        scan_string();
+        break;
+    case Trace::TYPE_ENUM:
+        scan_enum();
+        break;
+    case Trace::TYPE_BITMASK:
+        scan_bitmask();
+        break;
+    case Trace::TYPE_ARRAY:
+        scan_array();
+        break;
+    case Trace::TYPE_STRUCT:
+        scan_struct();
+        break;
+    case Trace::TYPE_BLOB:
+        scan_blob();
+        break;
+    case Trace::TYPE_OPAQUE:
+        scan_opaque();
+        break;
+    default:
+        std::cerr << "error: unknown type " << c << "\n";
+        exit(1);
+    case -1:
+        break;
+    }
+}
+
+
+Value *Parser::parse_sint() {
+    return new SInt(-(signed long long)read_uint());
+}
+
+
+void Parser::scan_sint() {
+    skip_uint();
+}
+
+
+Value *Parser::parse_uint() {
+    return new UInt(read_uint());
+}
+
+
+void Parser::scan_uint() {
+    skip_uint();
+}
+
+
+Value *Parser::parse_float() {
+    float value;
+    file->read(&value, sizeof value);
+    return new Float(value);
+}
+
+
+void Parser::scan_float() {
+    file->skip(sizeof(float));
+}
+
+
+Value *Parser::parse_double() {
+    double value;
+    file->read(&value, sizeof value);
+    return new Float(value);
+}
+
+
+void Parser::scan_double() {
+    file->skip(sizeof(double));
+}
+
+
+Value *Parser::parse_string() {
+    return new String(read_string());
+}
+
+
+void Parser::scan_string() {
+    skip_string();
+}
+
+
+Value *Parser::parse_enum() {
+    EnumSig *sig = parse_enum_sig();
+    return new Enum(sig);
+}
+
+
+void Parser::scan_enum() {
+    parse_enum_sig();
+}
+
+
+Value *Parser::parse_bitmask() {
+    BitmaskSig *sig = parse_bitmask_sig();
+
+    unsigned long long value = read_uint();
+
+    return new Bitmask(sig, value);
+}
+
+
+void Parser::scan_bitmask() {
+    parse_bitmask_sig();
+    skip_uint(); /* value */
+}
+
+
+Value *Parser::parse_array(void) {
+    size_t len = read_uint();
+    Array *array = new Array(len);
+    for (size_t i = 0; i < len; ++i) {
+        array->values[i] = parse_value();
+    }
+    return array;
+}
+
+
+void Parser::scan_array(void) {
+    size_t len = read_uint();
+    for (size_t i = 0; i < len; ++i) {
+        scan_value();
+    }
+}
+
+
+Value *Parser::parse_blob(void) {
+    size_t size = read_uint();
+    Blob *blob = new Blob(size);
+    if (size) {
+        file->read(blob->buf, (unsigned)size);
+    }
+    return blob;
+}
+
+
+void Parser::scan_blob(void) {
+    size_t size = read_uint();
+    if (size) {
+        file->skip(size);
+    }
+}
+
+
+Value *Parser::parse_struct() {
+    StructSig *sig = parse_struct_sig();
+    Struct *value = new Struct(sig);
+
+    for (size_t i = 0; i < sig->num_members; ++i) {
+        value->members[i] = parse_value();
+    }
+
+    return value;
+}
+
+
+void Parser::scan_struct() {
+    StructSig *sig = parse_struct_sig();
+    for (size_t i = 0; i < sig->num_members; ++i) {
+        scan_value();
+    }
+}
+
+
+Value *Parser::parse_opaque() {
+    unsigned long long addr;
+    addr = read_uint();
+    return new Pointer(addr);
+}
+
+
+void Parser::scan_opaque() {
+    skip_uint();
+}
+
+
+const char * Parser::read_string(void) {
+    size_t len = read_uint();
+    char * value = new char[len + 1];
+    if (len) {
+        file->read(value, (unsigned)len);
+    }
+    value[len] = 0;
+#if TRACE_VERBOSE
+    std::cerr << "\tSTRING \"" << value << "\"\n";
+#endif
+    return value;
+}
+
+
+void Parser::skip_string(void) {
+    size_t len = read_uint();
+    file->skip(len);
+}
+
+
+unsigned long long Parser::read_uint(void) {
+    unsigned long long value = 0;
+    int c;
+    unsigned shift = 0;
+    do {
+        c = file->getc();
+        if (c == -1) {
+            break;
+        }
+        value |= (unsigned long long)(c & 0x7f) << shift;
+        shift += 7;
+    } while(c & 0x80);
+#if TRACE_VERBOSE
+    std::cerr << "\tUINT " << value << "\n";
+#endif
+    return value;
+}
+
+
+void Parser::skip_uint(void) {
+    int c;
+    do {
+        c = file->getc();
+        if (c == -1) {
+            break;
+        }
+    } while(c & 0x80);
+}
+
+
+inline int Parser::read_byte(void) {
+    int c = file->getc();
+#if TRACE_VERBOSE
+    if (c < 0)
+        std::cerr << "\tEOF" << "\n";
+    else
+        std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n";
+#endif
+    return c;
+}
+
+
+inline void Parser::skip_byte(void) {
+    file->skip(1);
+}
+
+
+} /* namespace Trace */
diff --git a/common/trace_parser.hpp b/common/trace_parser.hpp
new file mode 100644 (file)
index 0000000..3aaa6d3
--- /dev/null
@@ -0,0 +1,197 @@
+/**************************************************************************
+ *
+ * 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 _TRACE_PARSER_HPP_
+#define _TRACE_PARSER_HPP_
+
+
+#include <iostream>
+#include <list>
+
+#include "trace_file.hpp"
+#include "trace_format.hpp"
+#include "trace_model.hpp"
+
+
+namespace Trace {
+
+
+struct ParseBookmark
+{
+    File::Offset offset;
+    unsigned next_call_no;
+};
+
+
+class Parser
+{
+protected:
+    File *file;
+
+    enum Mode {
+        FULL = 0,
+        SCAN,
+        SKIP
+    };
+
+    typedef std::list<Call *> CallList;
+    CallList calls;
+
+    // Helper template that extends a base signature structure, with additional
+    // parsing information.
+    template< class T >
+    struct SigState : public T {
+        // Offset in the file of where signature was defined.  It is used when
+        // reparsing to determine whether the signature definition is to be
+        // expected next or not.
+        File::Offset offset;
+    };
+
+    typedef SigState<FunctionSig> FunctionSigState;
+    typedef SigState<StructSig> StructSigState;
+    typedef SigState<EnumSig> EnumSigState;
+    typedef SigState<BitmaskSig> BitmaskSigState;
+
+    typedef std::vector<FunctionSigState *> FunctionMap;
+    typedef std::vector<StructSigState *> StructMap;
+    typedef std::vector<EnumSigState *> EnumMap;
+    typedef std::vector<BitmaskSigState *> BitmaskMap;
+
+    FunctionMap functions;
+    StructMap structs;
+    EnumMap enums;
+    BitmaskMap bitmasks;
+
+    unsigned next_call_no;
+
+public:
+    unsigned long long version;
+
+    Parser();
+
+    ~Parser();
+
+    bool open(const char *filename);
+
+    void close(void);
+
+    Call *parse_call(void) {
+        return parse_call(FULL);
+    }
+
+    bool supportsOffsets() const
+    {
+        return file->supportsOffsets();
+    }
+
+    void getBookmark(ParseBookmark &bookmark);
+
+    void setBookmark(const ParseBookmark &bookmark);
+
+    int percentRead()
+    {
+        return file->percentRead();
+    }
+
+    Call *scan_call() {
+        return parse_call(SCAN);
+    }
+
+protected:
+    Call *parse_call(Mode mode);
+
+    FunctionSig *parse_function_sig(void);
+    StructSig *parse_struct_sig();
+    EnumSig *parse_enum_sig();
+    BitmaskSig *parse_bitmask_sig();
+    
+    Call *parse_Call(Mode mode);
+
+    void parse_enter(Mode mode);
+
+    Call *parse_leave(Mode mode);
+
+    bool parse_call_details(Call *call, Mode mode);
+
+    void parse_arg(Call *call, Mode mode);
+
+    Value *parse_value(void);
+    void scan_value(void);
+    inline Value *parse_value(Mode mode) {
+        if (mode == FULL) {
+            return parse_value();
+        } else {
+            scan_value();
+            return NULL;
+        }
+    }
+
+    Value *parse_sint();
+    void scan_sint();
+
+    Value *parse_uint();
+    void scan_uint();
+
+    Value *parse_float();
+    void scan_float();
+
+    Value *parse_double();
+    void scan_double();
+
+    Value *parse_string();
+    void scan_string();
+
+    Value *parse_enum();
+    void scan_enum();
+
+    Value *parse_bitmask();
+    void scan_bitmask();
+
+    Value *parse_array(void);
+    void scan_array(void);
+
+    Value *parse_blob(void);
+    void scan_blob(void);
+
+    Value *parse_struct();
+    void scan_struct();
+
+    Value *parse_opaque();
+    void scan_opaque();
+
+    const char * read_string(void);
+    void skip_string(void);
+
+    unsigned long long read_uint(void);
+    void skip_uint(void);
+
+    inline int read_byte(void);
+    inline void skip_byte(void);
+};
+
+
+} /* namespace Trace */
+
+#endif /* _TRACE_PARSER_HPP_ */
diff --git a/common/trace_snappyfile.cpp b/common/trace_snappyfile.cpp
new file mode 100644 (file)
index 0000000..4dbe42d
--- /dev/null
@@ -0,0 +1,338 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Zack Rusin
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "trace_snappyfile.hpp"
+
+#include <snappy.h>
+
+#include <iostream>
+
+#include <assert.h>
+#include <string.h>
+
+using namespace Trace;
+
+/*
+ * Snappy file format.
+ * -------------------
+ *
+ * Snappy at its core is just a compressoin algorithm so we're
+ * creating a new file format which uses snappy compression
+ * to hold the trace data.
+ *
+ * The file is composed of a number of chunks, they are:
+ * chunk {
+ *     uint32 - specifying the length of the compressed data
+ *     compressed data, in little endian
+ * }
+ * File can contain any number of such chunks.
+ * The default size of an uncompressed chunk is specified in
+ * SNAPPY_CHUNK_SIZE.
+ *
+ * Note:
+ * Currently the default size for a a to-be-compressed data is
+ * 1mb, meaning that the compressed data will be <= 1mb.
+ * The reason it's 1mb is because it seems
+ * to offer a pretty good compression/disk io speed ratio
+ * but that might change.
+ *
+ */
+
+SnappyFile::SnappyFile(const std::string &filename,
+                              File::Mode mode)
+    : File(),
+      m_cache(0),
+      m_cachePtr(0),
+      m_cacheSize(0)
+{
+    size_t maxCompressedLength =
+        snappy::MaxCompressedLength(SNAPPY_CHUNK_SIZE);
+    m_compressedCache = new char[maxCompressedLength];
+}
+
+SnappyFile::~SnappyFile()
+{
+    delete [] m_compressedCache;
+    delete [] m_cache;
+}
+
+bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
+{
+    std::ios_base::openmode fmode = std::fstream::binary;
+    if (mode == File::Write) {
+        fmode |= (std::fstream::out | std::fstream::trunc);
+        createCache(SNAPPY_CHUNK_SIZE);
+    } else if (mode == File::Read) {
+        fmode |= std::fstream::in;
+    }
+
+    m_stream.open(filename.c_str(), fmode);
+
+    //read in the initial buffer if we're reading
+    if (m_stream.is_open() && mode == File::Read) {
+        m_stream.seekg(0, std::ios::end);
+        m_endPos = m_stream.tellg();
+        m_stream.seekg(0, std::ios::beg);
+
+        // read the snappy file identifier
+        unsigned char byte1, byte2;
+        m_stream >> byte1;
+        m_stream >> byte2;
+        assert(byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
+
+        flushReadCache();
+    } else if (m_stream.is_open() && mode == File::Write) {
+        // write the snappy file identifier
+        m_stream << SNAPPY_BYTE1;
+        m_stream << SNAPPY_BYTE2;
+    }
+    return m_stream.is_open();
+}
+
+bool SnappyFile::rawWrite(const void *buffer, size_t length)
+{
+    if (freeCacheSize() > length) {
+        memcpy(m_cachePtr, buffer, length);
+        m_cachePtr += length;
+    } else if (freeCacheSize() == length) {
+        memcpy(m_cachePtr, buffer, length);
+        m_cachePtr += length;
+        flushWriteCache();
+    } else {
+        int sizeToWrite = length;
+
+        while (sizeToWrite >= freeCacheSize()) {
+            int endSize = freeCacheSize();
+            int offset = length - sizeToWrite;
+            memcpy(m_cachePtr, (const char*)buffer + offset, endSize);
+            sizeToWrite -= endSize;
+            m_cachePtr += endSize;
+            flushWriteCache();
+        }
+        if (sizeToWrite) {
+            int offset = length - sizeToWrite;
+            memcpy(m_cachePtr, (const char*)buffer + offset, sizeToWrite);
+            m_cachePtr += sizeToWrite;
+        }
+    }
+
+    return true;
+}
+
+bool SnappyFile::rawRead(void *buffer, size_t length)
+{
+    if (endOfData()) {
+        return false;
+    }
+
+    if (freeCacheSize() >= length) {
+        memcpy(buffer, m_cachePtr, length);
+        m_cachePtr += length;
+    } else {
+        size_t sizeToRead = length;
+        size_t offset = 0;
+        while (sizeToRead) {
+            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
+            offset = length - sizeToRead;
+            memcpy((char*)buffer + offset, m_cachePtr, chunkSize);
+            m_cachePtr += chunkSize;
+            sizeToRead -= chunkSize;
+            if (sizeToRead > 0) {
+                flushReadCache();
+            }
+            if (!m_cacheSize) {
+                break;
+            }
+        }
+    }
+
+    return true;
+}
+
+int SnappyFile::rawGetc()
+{
+    int c = 0;
+    if (!rawRead(&c, 1))
+        return -1;
+    return c;
+}
+
+void SnappyFile::rawClose()
+{
+    if (m_mode == File::Write) {
+        flushWriteCache();
+    }
+    m_stream.close();
+    delete [] m_cache;
+    m_cache = NULL;
+    m_cachePtr = NULL;
+}
+
+void SnappyFile::rawFlush()
+{
+    assert(m_mode == File::Write);
+    flushWriteCache();
+    m_stream.flush();
+}
+
+void SnappyFile::flushWriteCache()
+{
+    size_t inputLength = usedCacheSize();
+
+    if (inputLength) {
+        size_t compressedLength;
+
+        ::snappy::RawCompress(m_cache, inputLength,
+                              m_compressedCache, &compressedLength);
+
+        writeCompressedLength(compressedLength);
+        m_stream.write(m_compressedCache, compressedLength);
+        m_cachePtr = m_cache;
+    }
+    assert(m_cachePtr == m_cache);
+}
+
+void SnappyFile::flushReadCache(size_t skipLength)
+{
+    //assert(m_cachePtr == m_cache + m_cacheSize);
+    m_currentOffset.chunk = m_stream.tellg();
+    size_t compressedLength;
+    compressedLength = readCompressedLength();
+
+    if (compressedLength) {
+        m_stream.read((char*)m_compressedCache, compressedLength);
+        ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
+                                        &m_cacheSize);
+        createCache(m_cacheSize);
+        if (skipLength < m_cacheSize) {
+            ::snappy::RawUncompress(m_compressedCache, compressedLength,
+                                    m_cache);
+        }
+    } else {
+        createCache(0);
+    }
+}
+
+void SnappyFile::createCache(size_t size)
+{
+    // TODO: only re-allocate if the current buffer is not big enough
+
+    if (m_cache) {
+        delete [] m_cache;
+    }
+
+    if (size) {
+        m_cache = new char[size];
+    } else {
+        m_cache = NULL;
+    }
+
+    m_cachePtr = m_cache;
+    m_cacheSize = size;
+}
+
+void SnappyFile::writeCompressedLength(size_t length)
+{
+    unsigned char buf[4];
+    buf[0] = length & 0xff; length >>= 8;
+    buf[1] = length & 0xff; length >>= 8;
+    buf[2] = length & 0xff; length >>= 8;
+    buf[3] = length & 0xff; length >>= 8;
+    assert(length == 0);
+    m_stream.write((const char *)buf, sizeof buf);
+}
+
+size_t SnappyFile::readCompressedLength()
+{
+    unsigned char buf[4];
+    size_t length;
+    m_stream.read((char *)buf, sizeof buf);
+    if (m_stream.fail()) {
+        length = 0;
+    } else {
+        length  =  (size_t)buf[0];
+        length |= ((size_t)buf[1] <<  8);
+        length |= ((size_t)buf[2] << 16);
+        length |= ((size_t)buf[3] << 24);
+    }
+    return length;
+}
+
+bool SnappyFile::supportsOffsets() const
+{
+    return true;
+}
+
+File::Offset SnappyFile::currentOffset()
+{
+    m_currentOffset.offsetInChunk = m_cachePtr - m_cache;
+    return m_currentOffset;
+}
+
+void SnappyFile::setCurrentOffset(const File::Offset &offset)
+{
+    // to remove eof bit
+    m_stream.clear();
+    // seek to the start of a chunk
+    m_stream.seekg(offset.chunk, std::ios::beg);
+    // load the chunk
+    flushReadCache();
+    assert(m_cacheSize >= offset.offsetInChunk);
+    // seek within our cache to the correct location within the chunk
+    m_cachePtr = m_cache + offset.offsetInChunk;
+
+}
+
+bool SnappyFile::rawSkip(size_t length)
+{
+    if (endOfData()) {
+        return false;
+    }
+
+    if (freeCacheSize() >= length) {
+        m_cachePtr += length;
+    } else {
+        size_t sizeToRead = length;
+        while (sizeToRead) {
+            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
+            m_cachePtr += chunkSize;
+            sizeToRead -= chunkSize;
+            if (sizeToRead > 0) {
+                flushReadCache(sizeToRead);
+            }
+            if (!m_cacheSize) {
+                break;
+            }
+        }
+    }
+
+    return true;
+}
+
+int SnappyFile::rawPercentRead()
+{
+    return 100 * (double(m_stream.tellg()) / double(m_endPos));
+}
diff --git a/common/trace_snappyfile.hpp b/common/trace_snappyfile.hpp
new file mode 100644 (file)
index 0000000..33159ec
--- /dev/null
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Zack Rusin
+ * 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 TRACE_SNAPPYFILE_HPP
+#define TRACE_SNAPPYFILE_HPP
+
+#include <assert.h>
+
+#include "trace_file.hpp"
+
+#include <string>
+#include <fstream>
+
+namespace snappy {
+    class File;
+}
+
+namespace Trace {
+
+#define SNAPPY_CHUNK_SIZE (1 * 1024 * 1024)
+
+#define SNAPPY_BYTE1 'a'
+#define SNAPPY_BYTE2 't'
+
+
+class SnappyFile : public File {
+public:
+    SnappyFile(const std::string &filename = std::string(),
+               File::Mode mode = File::Read);
+    virtual ~SnappyFile();
+
+    virtual bool supportsOffsets() const;
+    virtual File::Offset currentOffset();
+    virtual void setCurrentOffset(const File::Offset &offset);
+protected:
+    virtual bool rawOpen(const std::string &filename, File::Mode mode);
+    virtual bool rawWrite(const void *buffer, size_t length);
+    virtual bool rawRead(void *buffer, size_t length);
+    virtual int rawGetc();
+    virtual void rawClose();
+    virtual void rawFlush();
+    virtual bool rawSkip(size_t length);
+    virtual int rawPercentRead();
+
+private:
+    inline size_t usedCacheSize() const
+    {
+        assert(m_cachePtr >= m_cache);
+        return m_cachePtr - m_cache;
+    }
+    inline size_t freeCacheSize() const
+    {
+        assert(m_cacheSize >= usedCacheSize());
+        if (m_cacheSize > 0) {
+            return m_cacheSize - usedCacheSize();
+        } else {
+            return 0;
+        }
+    }
+    inline bool endOfData() const
+    {
+        return m_stream.eof() && freeCacheSize() == 0;
+    }
+    void flushWriteCache();
+    void flushReadCache(size_t skipLength = 0);
+    void createCache(size_t size);
+    void writeCompressedLength(size_t length);
+    size_t readCompressedLength();
+private:
+    std::fstream m_stream;
+    char *m_cache;
+    char *m_cachePtr;
+    size_t m_cacheSize;
+
+    char *m_compressedCache;
+
+    File::Offset m_currentOffset;
+    std::streampos m_endPos;
+};
+
+}
+
+#endif // TRACE_SNAPPYFILE_HPP
diff --git a/common/trace_writer.cpp b/common/trace_writer.cpp
new file mode 100644 (file)
index 0000000..5a5f1f7
--- /dev/null
@@ -0,0 +1,303 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2009 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.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "os.hpp"
+#include "trace_writer.hpp"
+#include "trace_snappyfile.hpp"
+#include "trace_format.hpp"
+
+
+namespace Trace {
+
+
+Writer::Writer() :
+    call_no(0)
+{
+    m_file = new Trace::SnappyFile;
+    close();
+}
+
+Writer::~Writer()
+{
+    close();
+    delete m_file;
+    m_file = NULL;
+}
+
+void
+Writer::close(void) {
+    m_file->close();
+}
+
+bool
+Writer::open(const char *filename) {
+    close();
+
+    if (!m_file->open(filename, File::Write)) {
+        return false;
+    }
+
+    call_no = 0;
+    functions.clear();
+    structs.clear();
+    enums.clear();
+    bitmasks.clear();
+
+    _writeUInt(TRACE_VERSION);
+
+    return true;
+}
+
+void inline
+Writer::_write(const void *sBuffer, size_t dwBytesToWrite) {
+    m_file->write(sBuffer, dwBytesToWrite);
+}
+
+void inline
+Writer::_writeByte(char c) {
+    _write(&c, 1);
+}
+
+void inline
+Writer::_writeUInt(unsigned long long value) {
+    char buf[2 * sizeof value];
+    unsigned len;
+
+    len = 0;
+    do {
+        assert(len < sizeof buf);
+        buf[len] = 0x80 | (value & 0x7f);
+        value >>= 7;
+        ++len;
+    } while (value);
+
+    assert(len);
+    buf[len - 1] &= 0x7f;
+
+    _write(buf, len);
+}
+
+void inline
+Writer::_writeFloat(float value) {
+    assert(sizeof value == 4);
+    _write((const char *)&value, sizeof value);
+}
+
+void inline
+Writer::_writeDouble(double value) {
+    assert(sizeof value == 8);
+    _write((const char *)&value, sizeof value);
+}
+
+void inline
+Writer::_writeString(const char *str) {
+    size_t len = strlen(str);
+    _writeUInt(len);
+    _write(str, len);
+}
+
+inline bool lookup(std::vector<bool> &map, size_t index) {
+    if (index >= map.size()) {
+        map.resize(index + 1);
+        return false;
+    } else {
+        return map[index];
+    }
+}
+
+unsigned Writer::beginEnter(const FunctionSig *sig) {
+    _writeByte(Trace::EVENT_ENTER);
+    _writeUInt(sig->id);
+    if (!lookup(functions, sig->id)) {
+        _writeString(sig->name);
+        _writeUInt(sig->num_args);
+        for (unsigned i = 0; i < sig->num_args; ++i) {
+            _writeString(sig->arg_names[i]);
+        }
+        functions[sig->id] = true;
+    }
+
+    return call_no++;
+}
+
+void Writer::endEnter(void) {
+    _writeByte(Trace::CALL_END);
+}
+
+void Writer::beginLeave(unsigned call) {
+    _writeByte(Trace::EVENT_LEAVE);
+    _writeUInt(call);
+}
+
+void Writer::endLeave(void) {
+    _writeByte(Trace::CALL_END);
+}
+
+void Writer::beginArg(unsigned index) {
+    _writeByte(Trace::CALL_ARG);
+    _writeUInt(index);
+}
+
+void Writer::beginReturn(void) {
+    _writeByte(Trace::CALL_RET);
+}
+
+void Writer::beginArray(size_t length) {
+    _writeByte(Trace::TYPE_ARRAY);
+    _writeUInt(length);
+}
+
+void Writer::beginStruct(const StructSig *sig) {
+    _writeByte(Trace::TYPE_STRUCT);
+    _writeUInt(sig->id);
+    if (!lookup(structs, sig->id)) {
+        _writeString(sig->name);
+        _writeUInt(sig->num_members);
+        for (unsigned i = 0; i < sig->num_members; ++i) {
+            _writeString(sig->member_names[i]);
+        }
+        structs[sig->id] = true;
+    }
+}
+
+void Writer::writeBool(bool value) {
+    _writeByte(value ? Trace::TYPE_TRUE : Trace::TYPE_FALSE);
+}
+
+void Writer::writeSInt(signed long long value) {
+    if (value < 0) {
+        _writeByte(Trace::TYPE_SINT);
+        _writeUInt(-value);
+    } else {
+        _writeByte(Trace::TYPE_UINT);
+        _writeUInt(value);
+    }
+}
+
+void Writer::writeUInt(unsigned long long value) {
+    _writeByte(Trace::TYPE_UINT);
+    _writeUInt(value);
+}
+
+void Writer::writeFloat(float value) {
+    _writeByte(Trace::TYPE_FLOAT);
+    _writeFloat(value);
+}
+
+void Writer::writeDouble(double value) {
+    _writeByte(Trace::TYPE_DOUBLE);
+    _writeDouble(value);
+}
+
+void Writer::writeString(const char *str) {
+    if (!str) {
+        Writer::writeNull();
+        return;
+    }
+    _writeByte(Trace::TYPE_STRING);
+    _writeString(str);
+}
+
+void Writer::writeString(const char *str, size_t len) {
+    if (!str) {
+        Writer::writeNull();
+        return;
+    }
+    _writeByte(Trace::TYPE_STRING);
+    _writeUInt(len);
+    _write(str, len);
+}
+
+void Writer::writeWString(const wchar_t *str) {
+    if (!str) {
+        Writer::writeNull();
+        return;
+    }
+    _writeByte(Trace::TYPE_STRING);
+    _writeString("<wide-string>");
+}
+
+void Writer::writeBlob(const void *data, size_t size) {
+    if (!data) {
+        Writer::writeNull();
+        return;
+    }
+    _writeByte(Trace::TYPE_BLOB);
+    _writeUInt(size);
+    if (size) {
+        _write(data, size);
+    }
+}
+
+void Writer::writeEnum(const EnumSig *sig) {
+    _writeByte(Trace::TYPE_ENUM);
+    _writeUInt(sig->id);
+    if (!lookup(enums, sig->id)) {
+        _writeString(sig->name);
+        Writer::writeSInt(sig->value);
+        enums[sig->id] = true;
+    }
+}
+
+void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
+    _writeByte(Trace::TYPE_BITMASK);
+    _writeUInt(sig->id);
+    if (!lookup(bitmasks, sig->id)) {
+        _writeUInt(sig->num_flags);
+        for (unsigned i = 0; i < sig->num_flags; ++i) {
+            if (i != 0 && sig->flags[i].value == 0) {
+                OS::DebugMessage("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name);
+            }
+            _writeString(sig->flags[i].name);
+            _writeUInt(sig->flags[i].value);
+        }
+        bitmasks[sig->id] = true;
+    }
+    _writeUInt(value);
+}
+
+void Writer::writeNull(void) {
+    _writeByte(Trace::TYPE_NULL);
+}
+
+void Writer::writeOpaque(const void *addr) {
+    if (!addr) {
+        Writer::writeNull();
+        return;
+    }
+    _writeByte(Trace::TYPE_OPAQUE);
+    _writeUInt((size_t)addr);
+}
+
+
+} /* namespace Trace */
+
diff --git a/common/trace_writer.hpp b/common/trace_writer.hpp
new file mode 100644 (file)
index 0000000..dfb76b2
--- /dev/null
@@ -0,0 +1,145 @@
+/**************************************************************************
+ *
+ * Copyright 2007-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.
+ *
+ **************************************************************************/
+
+/*
+ * Trace writing functions.
+ */
+
+#ifndef _TRACE_WRITER_HPP_
+#define _TRACE_WRITER_HPP_
+
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "trace_model.hpp"
+
+
+namespace Trace {
+    class File;
+
+    class Writer {
+    protected:
+        File *m_file;
+        unsigned call_no;
+
+        std::vector<bool> functions;
+        std::vector<bool> structs;
+        std::vector<bool> enums;
+        std::vector<bool> bitmasks;
+
+    public:
+        Writer();
+        ~Writer();
+
+        bool open(const char *filename);
+        void close(void);
+
+        unsigned beginEnter(const FunctionSig *sig);
+        void endEnter(void);
+
+        void beginLeave(unsigned call);
+        void endLeave(void);
+
+        void beginArg(unsigned index);
+        inline void endArg(void) {}
+
+        void beginReturn(void);
+        inline void endReturn(void) {}
+
+        void beginArray(size_t length);
+        inline void endArray(void) {}
+
+        inline void beginElement(void) {}
+        inline void endElement(void) {}
+
+        void beginStruct(const StructSig *sig);
+        inline void endStruct(void) {}
+
+        void writeBool(bool value);
+        void writeSInt(signed long long value);
+        void writeUInt(unsigned long long value);
+        void writeFloat(float value);
+        void writeDouble(double value);
+        void writeString(const char *str);
+        void writeString(const char *str, size_t size);
+        void writeWString(const wchar_t *str);
+        void writeBlob(const void *data, size_t size);
+        void writeEnum(const EnumSig *sig);
+        void writeBitmask(const BitmaskSig *sig, unsigned long long value);
+        void writeNull(void);
+        void writeOpaque(const void *ptr);
+
+        void writeCall(Call *call);
+
+    protected:
+        void inline _write(const void *sBuffer, size_t dwBytesToWrite);
+        void inline _writeByte(char c);
+        void inline _writeUInt(unsigned long long value);
+        void inline _writeFloat(float value);
+        void inline _writeDouble(double value);
+        void inline _writeString(const char *str);
+
+    };
+
+    /**
+     * A specialized Writer class, mean to trace the current process.
+     *
+     * In particular:
+     * - it creates a trace file based on the current process name
+     * - uses mutexes to allow tracing from multiple threades
+     * - flushes the output to ensure the last call is traced in event of
+     *   abnormal termination
+     */
+    class LocalWriter : public Writer {
+    protected:
+        int acquired;
+
+    public:
+        /**
+         * Should never called directly -- use localWriter singleton below instead.
+         */
+        LocalWriter();
+        ~LocalWriter();
+
+        void open(void);
+
+        unsigned beginEnter(const FunctionSig *sig);
+        void endEnter(void);
+
+        void beginLeave(unsigned call);
+        void endLeave(void);
+
+        void flush(void);
+    };
+
+    /**
+     * Singleton.
+     */
+    extern LocalWriter localWriter;
+}
+
+#endif /* _TRACE_WRITER_HPP_ */
diff --git a/formatter.hpp b/formatter.hpp
deleted file mode 100644 (file)
index 181e2d1..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-/*
- * Helpers for coloring output.
- */
-
-#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 void apply(std::ostream &) const {}
-};
-
-
-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) const { return new Attribute; }
-};
-
-
-class AnsiAttribute : public Attribute {
-protected:
-    const char *escape;
-public:
-    AnsiAttribute(const char *_escape) : escape(_escape) {}
-    void apply(std::ostream& os) const {
-        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) {
-    attr->apply(os);
-    return os;
-}
-
-
-#ifdef _WIN32
-
-#include <windows.h>
-
-class WindowsAttribute : public Attribute {
-protected:
-    WORD wAttributes;
-public:
-    WindowsAttribute(WORD _wAttributes) : wAttributes(_wAttributes) {}
-    void 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;
-        }
-        HANDLE hConsoleOutput = GetStdHandle(nStdHandleOutput);
-        if (hConsoleOutput == INVALID_HANDLE_VALUE) {
-            return;
-        }
-
-        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(bool color = true) {
-    if (color) {
-#ifdef _WIN32
-        return new WindowsFormatter;
-#else
-        return new AnsiFormatter;
-#endif
-    } else {
-        return new Formatter;
-    }
-}
-
-
-} /* namespace Formatter */
-
-
-#endif /* _FORMATTER_HPP_ */
diff --git a/image.cpp b/image.cpp
deleted file mode 100644 (file)
index 4da9c13..0000000
--- a/image.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-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.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <math.h>
-
-#include "image.hpp"
-
-
-namespace Image {
-
-
-double Image::compare(Image &ref)
-{
-    if (width != ref.width ||
-        height != ref.height ||
-        channels != ref.channels) {
-        return 0.0;
-    }
-
-    const unsigned char *pSrc = start();
-    const unsigned char *pRef = ref.start();
-
-    assert(channels >= 3);
-
-    unsigned long long error = 0;
-    for (unsigned y = 0; y < height; ++y) {
-        for (unsigned  x = 0; x < width; ++x) {
-            // FIXME: Ignore alpha channel until we are able to pick a visual
-            // that matches the traces
-            for (unsigned  c = 0; c < 3; ++c) {
-                int delta = pSrc[x*channels + c] - pRef[x*channels + c];
-                error += delta*delta;
-            }
-        }
-
-        pSrc += stride();
-        pRef += ref.stride();
-    }
-
-    double numerator = error*2 + 1;
-    double denominator = height*width*3ULL*255ULL*255ULL*2;
-    double quotient = numerator/denominator;
-
-    // Precision in bits
-    double precision = -log(quotient)/log(2.0);
-
-    return precision;
-}
-
-
-} /* namespace Image */
diff --git a/image.hpp b/image.hpp
deleted file mode 100644 (file)
index dc53ec9..0000000
--- a/image.hpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008-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.
- *
- **************************************************************************/
-
-/*
- * Image I/O.
- */
-
-#ifndef _IMAGE_HPP_
-#define _IMAGE_HPP_
-
-
-#include <fstream>
-
-
-namespace Image {
-
-
-class Image {
-public:
-    unsigned width;
-    unsigned height;
-    unsigned channels;
-
-    // Flipped vertically or not
-    bool flipped;
-
-    // Pixels in RGBA format
-    unsigned char *pixels;
-
-    inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false) : 
-        width(w),
-        height(h),
-        channels(c),
-        flipped(f),
-        pixels(new unsigned char[h*w*c])
-    {}
-
-    inline ~Image() {
-        delete [] pixels;
-    }
-
-    inline unsigned char *start(void) {
-        return flipped ? pixels + (height - 1)*width*channels : pixels;
-    }
-
-    inline const unsigned char *start(void) const {
-        return flipped ? pixels + (height - 1)*width*channels : pixels;
-    }
-
-    inline unsigned char *end(void) {
-        return flipped ? pixels - width*channels : pixels + height*width*channels;
-    }
-
-    inline const unsigned char *end(void) const {
-        return flipped ? pixels - width*channels : pixels + height*width*channels;
-    }
-
-    inline signed stride(void) const {
-        return flipped ? -width*channels : width*channels;
-    }
-
-    bool writeBMP(const char *filename) const;
-
-    void writePNM(std::ostream &os, const char *comment = NULL) const;
-
-    inline bool writePNM(const char *filename, const char *comment = NULL) const {
-        std::ofstream os(filename, std::ofstream::binary);
-        if (!os) {
-            return false;
-        }
-        writePNM(os, comment);
-        return true;
-    }
-
-    bool writePNG(const char *filename) const;
-
-    double compare(Image &ref);
-};
-
-bool writePixelsToBuffer(unsigned char *pixels,
-                         unsigned w, unsigned h, unsigned numChannels,
-                         bool flipped,
-                         char **buffer,
-                         int *size);
-
-Image *
-readPNG(const char *filename);
-
-
-} /* namespace Image */
-
-
-#endif /* _IMAGE_HPP_ */
diff --git a/image_bmp.cpp b/image_bmp.cpp
deleted file mode 100644 (file)
index 346f39a..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-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.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "image.hpp"
-
-
-namespace Image {
-
-
-#pragma pack(push,2)
-struct FileHeader {
-    uint16_t bfType;
-    uint32_t bfSize;
-    uint16_t bfReserved1;
-    uint16_t bfReserved2;
-    uint32_t bfOffBits;
-};
-#pragma pack(pop)
-
-struct InfoHeader {
-    uint32_t biSize;
-    int32_t biWidth;
-    int32_t biHeight;
-    uint16_t biPlanes;
-    uint16_t biBitCount;
-    uint32_t biCompression;
-    uint32_t biSizeImage;
-    int32_t biXPelsPerMeter;
-    int32_t biYPelsPerMeter;
-    uint32_t biClrUsed;
-    uint32_t biClrImportant;
-};
-
-struct Pixel {
-    uint8_t rgbBlue;
-    uint8_t rgbGreen;
-    uint8_t rgbRed;
-    uint8_t rgbAlpha;
-};
-
-
-bool
-Image::writeBMP(const char *filename) const {
-    assert(channels == 4);
-
-    struct FileHeader bmfh;
-    struct InfoHeader bmih;
-    unsigned x, y;
-
-    bmfh.bfType = 0x4d42;
-    bmfh.bfSize = 14 + 40 + height*width*4;
-    bmfh.bfReserved1 = 0;
-    bmfh.bfReserved2 = 0;
-    bmfh.bfOffBits = 14 + 40;
-
-    bmih.biSize = 40;
-    bmih.biWidth = width;
-    bmih.biHeight = height;
-    bmih.biPlanes = 1;
-    bmih.biBitCount = 32;
-    bmih.biCompression = 0;
-    bmih.biSizeImage = height*width*4;
-    bmih.biXPelsPerMeter = 0;
-    bmih.biYPelsPerMeter = 0;
-    bmih.biClrUsed = 0;
-    bmih.biClrImportant = 0;
-
-    std::ofstream stream(filename, std::ofstream::binary);
-
-    if (!stream) {
-        return false;
-    }
-
-    stream.write((const char *)&bmfh, 14);
-    stream.write((const char *)&bmih, 40);
-
-    unsigned stride = width*4;
-
-    if (flipped) {
-        for (y = 0; y < height; ++y) {
-            const unsigned char *ptr = pixels + y * stride;
-            for (x = 0; x < width; ++x) {
-                struct Pixel pixel;
-                pixel.rgbRed   = ptr[x*4 + 0];
-                pixel.rgbGreen = ptr[x*4 + 1];
-                pixel.rgbBlue  = ptr[x*4 + 2];
-                pixel.rgbAlpha = ptr[x*4 + 3];
-                stream.write((const char *)&pixel, 4);
-            }
-        }
-    } else {
-        y = height;
-        while (y--) {
-            const unsigned char *ptr = pixels + y * stride;
-            for (x = 0; x < width; ++x) {
-                struct Pixel pixel;
-                pixel.rgbRed   = ptr[x*4 + 0];
-                pixel.rgbGreen = ptr[x*4 + 1];
-                pixel.rgbBlue  = ptr[x*4 + 2];
-                pixel.rgbAlpha = ptr[x*4 + 3];
-                stream.write((const char *)&pixel, 4);
-            }
-        }
-    }
-
-    stream.close();
-
-    return true;
-}
-
-
-} /* namespace Image */
diff --git a/image_png.cpp b/image_png.cpp
deleted file mode 100644 (file)
index fd22213..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-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.
- *
- **************************************************************************/
-
-
-#include <zlib.h>
-#include <png.h>
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <fstream>
-
-#include "image.hpp"
-
-
-namespace Image {
-
-
-bool
-Image::writePNG(const char *filename) const {
-    FILE *fp;
-    png_structp png_ptr;
-    png_infop info_ptr;
-
-    fp = fopen(filename, "wb");
-    if (!fp)
-        goto no_fp;
-
-    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-    if (!png_ptr)
-        goto no_png;
-
-    info_ptr = png_create_info_struct(png_ptr);
-    if (!info_ptr) {
-        png_destroy_write_struct(&png_ptr,  NULL);
-        goto no_png;
-    }
-
-    if (setjmp(png_jmpbuf(png_ptr))) {
-        png_destroy_write_struct(&png_ptr, &info_ptr);
-        goto no_png;
-    }
-
-    png_init_io(png_ptr, fp);
-
-    int color_type;
-    switch (channels) {
-    case 4:
-        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
-        break;
-    case 3:
-        color_type = PNG_COLOR_TYPE_RGB;
-        break;
-    case 2:
-        color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
-        break;
-    case 1:
-        color_type = PNG_COLOR_TYPE_GRAY;
-        break;
-    default:
-        assert(0);
-        return false;
-    }
-
-    png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type,
-        PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
-    png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
-
-    png_write_info(png_ptr, info_ptr);
-
-    if (!flipped) {
-        for (unsigned y = 0; y < height; ++y) {
-            png_bytep row = (png_bytep)(pixels + y*width*channels);
-            png_write_rows(png_ptr, &row, 1);
-        }
-    } else {
-        unsigned y = height;
-        while (y--) {
-            png_bytep row = (png_bytep)(pixels + y*width*channels);
-            png_write_rows(png_ptr, &row, 1);
-        }
-    }
-
-    png_write_end(png_ptr, info_ptr);
-    png_destroy_write_struct(&png_ptr, &info_ptr);
-
-    fclose(fp);
-    return true;
-
-no_png:
-    fclose(fp);
-no_fp:
-    return false;
-}
-
-
-Image *
-readPNG(const char *filename)
-{
-    FILE *fp;
-    png_structp png_ptr;
-    png_infop info_ptr;
-    png_infop end_info;
-    Image *image;
-
-    fp = fopen(filename, "rb");
-    if (!fp)
-        goto no_fp;
-
-    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-    if (!png_ptr)
-        goto no_png;
-
-    info_ptr = png_create_info_struct(png_ptr);
-    if (!info_ptr) {
-        png_destroy_read_struct(&png_ptr, NULL, NULL);
-        goto no_png;
-    }
-
-    end_info = png_create_info_struct(png_ptr);
-    if (!end_info) {
-        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-        goto no_png;
-    }
-
-    if (setjmp(png_jmpbuf(png_ptr))) {
-        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
-        goto no_png;
-    }
-
-    png_init_io(png_ptr, fp);
-
-    png_read_info(png_ptr, info_ptr);
-
-    png_uint_32 width, height;
-    int bit_depth, color_type, interlace_type, compression_type, filter_method;
-
-    png_get_IHDR(png_ptr, info_ptr,
-                 &width, &height,
-                 &bit_depth, &color_type, &interlace_type,
-                 &compression_type, &filter_method);
-
-    image = new Image(width, height);
-    if (!image)
-        goto no_image;
-
-    /* Convert to RGBA8 */
-    if (color_type == PNG_COLOR_TYPE_PALETTE)
-        png_set_palette_to_rgb(png_ptr);
-    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
-        png_set_expand_gray_1_2_4_to_8(png_ptr);
-    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
-        png_set_tRNS_to_alpha(png_ptr);
-    if (bit_depth == 16)
-        png_set_strip_16(png_ptr);
-
-    for (unsigned y = 0; y < height; ++y) {
-        png_bytep row = (png_bytep)(image->pixels + y*width*4);
-        png_read_row(png_ptr, row, NULL);
-    }
-
-    png_read_end(png_ptr, info_ptr);
-    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
-    fclose(fp);
-    return image;
-
-no_image:
-    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
-no_png:
-    fclose(fp);
-no_fp:
-    return NULL;
-}
-
-
-struct png_tmp_buffer
-{
-    char *buffer;
-    size_t size;
-};
-
-static void
-pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length)
-{
-    struct png_tmp_buffer *buf = (struct png_tmp_buffer*) png_get_io_ptr(png_ptr);
-    size_t nsize = buf->size + length;
-
-    /* allocate or grow buffer */
-    if (buf->buffer)
-        buf->buffer = (char*)realloc(buf->buffer, nsize);
-    else
-        buf->buffer = (char*)malloc(nsize);
-
-    if (!buf->buffer)
-        png_error(png_ptr, "Buffer allocation error");
-
-    memcpy(buf->buffer + buf->size, data, length);
-    buf->size += length;
-}
-
-bool writePixelsToBuffer(unsigned char *pixels,
-                         unsigned width, unsigned height, unsigned numChannels,
-                         bool flipped,
-                         char **buffer,
-                         int *size)
-{
-    struct png_tmp_buffer png_mem;
-    png_structp png_ptr;
-    png_infop info_ptr;
-    int type;
-
-    png_mem.buffer = NULL;
-    png_mem.size = 0;
-
-    switch (numChannels) {
-    case 4:
-        type = PNG_COLOR_TYPE_RGB_ALPHA;
-        break;
-    case 3:
-        type = PNG_COLOR_TYPE_RGB;
-        break;
-    case 2:
-        type = PNG_COLOR_TYPE_GRAY_ALPHA;
-        break;
-    case 1:
-        type = PNG_COLOR_TYPE_GRAY;
-        break;
-    default:
-        goto no_png;
-    }
-
-    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-    if (!png_ptr)
-        goto no_png;
-
-    info_ptr = png_create_info_struct(png_ptr);
-    if (!info_ptr) {
-        png_destroy_write_struct(&png_ptr,  NULL);
-        goto no_png;
-    }
-
-    if (setjmp(png_jmpbuf(png_ptr))) {
-        png_destroy_write_struct(&png_ptr, &info_ptr);
-        goto no_png;
-    }
-
-    png_set_write_fn(png_ptr, &png_mem, pngWriteCallback, NULL);
-
-    png_set_IHDR(png_ptr, info_ptr, width, height, 8,
-                 type, PNG_INTERLACE_NONE,
-                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
-    png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
-
-    png_write_info(png_ptr, info_ptr);
-
-    if (!flipped) {
-        for (unsigned y = 0; y < height; ++y) {
-            png_bytep row = (png_bytep)(pixels + y*width*numChannels);
-            png_write_rows(png_ptr, &row, 1);
-        }
-    } else {
-        unsigned y = height;
-        while (y--) {
-            png_bytep row = (png_bytep)(pixels + y*width*numChannels);
-            png_write_rows(png_ptr, &row, 1);
-        }
-    }
-
-    png_write_end(png_ptr, info_ptr);
-    png_destroy_write_struct(&png_ptr, &info_ptr);
-
-    *buffer = png_mem.buffer;
-    *size = png_mem.size;
-
-    return true;
-
-no_png:
-    *buffer = NULL;
-    *size = 0;
-
-    if (png_mem.buffer)
-        free(png_mem.buffer);
-    return false;
-}
-
-} /* namespace Image */
diff --git a/image_pnm.cpp b/image_pnm.cpp
deleted file mode 100644 (file)
index 5397a1a..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * Copyright 2008-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.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <string.h>
-#include <stdint.h>
-
-#include "image.hpp"
-
-
-namespace Image {
-
-/**
- * http://en.wikipedia.org/wiki/Netpbm_format
- * http://netpbm.sourceforge.net/doc/ppm.html
- */
-void
-Image::writePNM(std::ostream &os, const char *comment) const {
-    assert(channels == 1 || channels >= 3);
-
-    os << (channels == 1 ? "P5" : "P6") << "\n";
-    if (comment) {
-        os << "#" << comment << "\n";
-    }
-    os << width << " " << height << "\n";
-    os << "255" << "\n";
-
-    const unsigned char *row;
-
-    if (channels == 1 || channels == 3) {
-        for (row = start(); row != end(); row += stride()) {
-            os.write((const char *)row, width*channels);
-        }
-    } else {
-        unsigned char *tmp = new unsigned char[width*3];
-        if (channels == 4) {
-            for (row = start(); row != end(); row += stride()) {
-                const uint32_t *src = (const uint32_t *)row;
-                uint32_t *dst = (uint32_t *)tmp;
-                unsigned x;
-                for (x = 0; x + 4 <= width; x += 4) {
-                    /*
-                     * It's much faster to access dwords than bytes.
-                     *
-                     * FIXME: Big-endian version.
-                     */
-
-                    uint32_t rgba0 = *src++ & 0xffffff;
-                    uint32_t rgba1 = *src++ & 0xffffff;
-                    uint32_t rgba2 = *src++ & 0xffffff;
-                    uint32_t rgba3 = *src++ & 0xffffff;
-                    uint32_t rgb0 = rgba0
-                                  | (rgba1 << 24);
-                    uint32_t rgb1 = (rgba1 >> 8)
-                                  | (rgba2 << 16);
-                    uint32_t rgb2 = (rgba2 >> 16)
-                                  | (rgba3 << 8);
-                    *dst++ = rgb0;
-                    *dst++ = rgb1;
-                    *dst++ = rgb2;
-                }
-                for (; x < width; ++x) {
-                    tmp[x*3 + 0] = row[x*4 + 0];
-                    tmp[x*3 + 1] = row[x*4 + 1];
-                    tmp[x*3 + 2] = row[x*4 + 2];
-                }
-                os.write((const char *)tmp, width*3);
-            }
-        } else if (channels == 2) {
-            for (row = start(); row != end(); row += stride()) {
-                const unsigned char *src = row;
-                unsigned char *dst = tmp;
-                for (unsigned x = 0; x < width; ++x) {
-                    *dst++ = *src++;
-                    *dst++ = *src++;
-                    *dst++ = 0;
-                }
-                os.write((const char *)tmp, width*3);
-            }
-        } else {
-            assert(0);
-        }
-        delete [] tmp;
-    }
-}
-
-
-} /* namespace Image */
diff --git a/json.hpp b/json.hpp
deleted file mode 100644 (file)
index 9e6b960..0000000
--- a/json.hpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * 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.
- *
- **************************************************************************/
-
-/*
- * Trace writing functions.
- */
-
-#ifndef _JSON_HPP_
-#define _JSON_HPP_
-
-#include <assert.h>
-#include <stddef.h>
-#include <wchar.h>
-
-#include <iomanip>
-#include <ostream>
-#include <string>
-
-
-class JSONWriter
-{
-private:
-    std::ostream &os;
-
-    int level;
-    bool value;
-    char space;
-
-    void newline(void) {
-        os << "\n";
-        for (int i = 0; i < level; ++i) 
-            os << "  ";
-    }
-
-    void separator(void) {
-        if (value) {
-            os << ",";
-            switch (space) {
-            case '\0':
-                break;
-            case '\n':
-                newline();
-                break;
-            default:
-                os << space;
-                break;
-            }
-        } else {
-            if (space == '\n') {
-                newline();
-            }
-        }
-    }
-
-    void escapeAsciiString(const char *str) {
-        os << "\"";
-
-        const unsigned char *src = (const unsigned char *)str;
-        unsigned char c;
-        while ((c = *src++)) {
-            if ((c == '\"') ||
-                (c == '\\')) {
-                // escape character
-                os << '\\' << (unsigned char)c;
-            } else if ((c >= 0x20 && c <= 0x7e) ||
-                        c == '\t' ||
-                        c == '\r' ||
-                        c == '\n') {
-                // pass-through character
-                os << (unsigned char)c;
-            } else {
-                assert(0);
-                os << "?";
-            }
-        }
-
-        os << "\"";
-    }
-
-    void escapeUnicodeString(const char *str) {
-        os << "\"";
-
-        const char *locale = setlocale(LC_CTYPE, "");
-        const char *src = str;
-        mbstate_t state;
-
-        memset(&state, 0, sizeof state);
-
-        do {
-            // Convert characters one at a time in order to recover from
-            // conversion errors
-            wchar_t c;
-            size_t written = mbsrtowcs(&c, &src, 1, &state);
-            if (written == 0) {
-                // completed
-                break;
-            } if (written == (size_t)-1) {
-                // conversion error -- skip 
-                os << "?";
-                do {
-                    ++src;
-                } while (*src & 0x80);
-            } else if ((c == '\"') ||
-                       (c == '\\')) {
-                // escape character
-                os << '\\' << (unsigned char)c;
-            } else if ((c >= 0x20 && c <= 0x7e) ||
-                        c == '\t' ||
-                        c == '\r' ||
-                        c == '\n') {
-                // pass-through character
-                os << (unsigned char)c;
-            } else {
-                // unicode
-                os << "\\u" << std::setfill('0') << std::hex << std::setw(4) << (unsigned)c;
-                os << std::dec;
-            }
-        } while (src);
-
-        setlocale(LC_CTYPE, locale);
-
-        os << "\"";
-    }
-
-    void encodeBase64String(const unsigned char *bytes, size_t size) {
-        const char *table64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-        unsigned char c0, c1, c2, c3;
-        char buf[4];
-        unsigned written;
-
-        os << "\"";
-
-        written = 0;
-        while (size >= 3) {
-            c0 = bytes[0] >> 2;
-            c1 = ((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xf0) >> 4);
-            c2 = ((bytes[1] & 0x0f) << 2) | ((bytes[2] & 0xc0) >> 6);
-            c3 = bytes[2] & 0x3f;
-
-            buf[0] = table64[c0];
-            buf[1] = table64[c1];
-            buf[2] = table64[c2];
-            buf[3] = table64[c3];
-
-            os.write(buf, 4);
-
-            bytes += 3;
-            size -= 3;
-            ++written;
-
-            if (written >= 76/4 && size) {
-                os << "\n";
-                written = 0;
-            }
-        }
-
-        if (size > 0) {
-            c0 = bytes[0] >> 2;
-            c1 = ((bytes[0] & 0x03) << 4);
-            buf[2] = '=';
-            buf[3] = '=';
-            
-            if (size > 1) {
-                c1 |= ((bytes[1] & 0xf0) >> 4);
-                c2 = ((bytes[1] & 0x0f) << 2);
-                if (size > 2) {
-                    c2 |= ((bytes[2] & 0xc0) >> 6);
-                    c3 = bytes[2] & 0x3f;
-                    buf[3] = table64[c3];
-                }
-                buf[2] = table64[c2];
-            }
-            buf[1] = table64[c1];
-            buf[0] = table64[c0];
-
-            os.write(buf, 4);
-        }
-
-        os << "\"";
-    }
-
-public:
-    JSONWriter(std::ostream &_os) : 
-        os(_os), 
-        level(0),
-        value(false),
-        space(0)
-    {
-        beginObject();
-    }
-
-    ~JSONWriter() {
-        endObject();
-        newline();
-    }
-
-    inline void beginObject() {
-        separator();
-        os << "{";
-        ++level;
-        value = false;
-    }
-
-    inline void endObject() {
-        --level;
-        if (value)
-            newline();
-        os << "}";
-        value = true;
-        space = '\n';
-    }
-
-    inline void beginMember(const char * name) {
-        space = 0;
-        separator();
-        newline();
-        escapeAsciiString(name);
-        os << ": ";
-        value = false;
-    }
-
-    inline void beginMember(const std::string &name) {
-        beginMember(name.c_str());
-    }
-
-    inline void endMember(void) {
-        assert(value);
-        value = true;
-        space = 0;
-    }
-
-    inline void beginArray() {
-        separator();
-        os << "[";
-        ++level;
-        value = false;
-        space = 0;
-    }
-
-    inline void endArray(void) {
-        --level;
-        if (space == '\n') {
-            newline();
-        }
-        os << "]";
-        value = true;
-        space = '\n';
-    }
-
-    inline void writeString(const char *s) {
-        separator();
-        escapeUnicodeString(s);
-        value = true;
-        space = ' ';
-    }
-
-    inline void writeString(const std::string &s) {
-        writeString(s.c_str());
-    }
-
-    inline void writeBase64(const void *bytes, size_t size) {
-        separator();
-        encodeBase64String((const unsigned char *)bytes, size);
-        value = true;
-        space = ' ';
-    }
-
-    inline void writeNull(void) {
-        separator();
-        os << "null";
-        value = true;
-        space = ' ';
-    }
-
-    inline void writeBool(bool b) {
-        separator();
-        os << (b ? "true" : "false");
-        value = true;
-        space = ' ';
-    }
-
-    template<class T>
-    inline void writeNumber(T n) {
-        if (n != n) {
-            // NaN
-            writeNull();
-        } else {
-            separator();
-            os << std::dec << std::setprecision(9) << n;
-            value = true;
-            space = ' ';
-        }
-    }
-    
-    inline void writeStringMember(const char *name, const char *s) {
-        beginMember(name);
-        writeString(s);
-        endMember();
-    }
-
-    inline void writeBoolMember(const char *name, bool b) {
-        beginMember(name);
-        writeBool(b);
-        endMember();
-    }
-
-    template<class T>
-    inline void writeNumberMember(const char *name, T n) {
-        beginMember(name);
-        writeNumber(n);
-        endMember();
-    }
-};
-
-#endif /* _JSON_HPP_ */
diff --git a/os.hpp b/os.hpp
deleted file mode 100644 (file)
index 8e487b5..0000000
--- a/os.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-/*
- * Simple OS abstraction layer.
- */
-
-#ifndef _OS_HPP_
-#define _OS_HPP_
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#ifdef _WIN32
-#ifndef snprintf
-#define snprintf _snprintf
-#endif
-#ifndef vsnprintf
-#define vsnprintf _vsnprintf
-#endif
-#define PATH_SEP '\\'
-#else /* !_WIN32 */
-#define PATH_SEP '/'
-#endif /* !_WIN32 */
-
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
-
-namespace OS {
-
-void AcquireMutex(void);
-
-void ReleaseMutex(void);
-
-bool GetProcessName(char *str, size_t size);
-bool GetCurrentDir(char *str, size_t size);
-
-void DebugMessage(const char *format, ...)
-#ifdef __GNUC__
-    __attribute__ ((format (printf, 1, 2)))
-#endif
-;
-
-#if defined _WIN32 || defined __CYGWIN__
-  /* We always use .def files on windows for now */
-  #if 0
-  #define PUBLIC __declspec(dllexport)
-  #else
-  #define PUBLIC
-  #endif
-  #define PRIVATE
-#else
-  #if __GNUC__ >= 4
-    #define PUBLIC __attribute__ ((visibility("default")))
-    #define PRIVATE __attribute__ ((visibility("hidden")))
-  #else
-    #define PUBLIC
-    #define PRIVATE
-  #endif
-#endif
-
-/**
- * Get the current time in microseconds from an unknown base.
- */
-long long GetTime(void);
-
-void Abort(void);
-
-void SetExceptionCallback(void (*callback)(void));
-void ResetExceptionCallback(void);
-
-} /* namespace OS */
-
-#endif /* _OS_HPP_ */
diff --git a/os_posix.cpp b/os_posix.cpp
deleted file mode 100644 (file)
index 98a790b..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010-2011 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.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <unistd.h>
-#include <sys/time.h>
-#include <pthread.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-
-#ifdef __APPLE__
-#include <mach-o/dyld.h>
-#endif
-
-#include "os.hpp"
-
-
-namespace OS {
-
-
-static pthread_mutex_t 
-mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-void
-AcquireMutex(void)
-{
-    pthread_mutex_lock(&mutex);
-}
-
-
-void
-ReleaseMutex(void)
-{
-    pthread_mutex_unlock(&mutex);
-}
-
-
-bool
-GetProcessName(char *str, size_t size)
-{
-    char szProcessPath[PATH_MAX + 1];
-    char *lpProcessName;
-
-    // http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
-#ifdef __APPLE__
-    uint32_t len = sizeof szProcessPath;
-    if (_NSGetExecutablePath(szProcessPath, &len) != 0) {
-        *str = 0;
-        return false;
-    }
-#else
-    ssize_t len;
-    len = readlink("/proc/self/exe", szProcessPath, sizeof(szProcessPath) - 1);
-    if (len == -1) {
-        // /proc/self/exe is not available on setuid processes, so fallback to
-        // /proc/self/cmdline.
-        int fd = open("/proc/self/cmdline", O_RDONLY);
-        if (fd >= 0) {
-            len = read(fd, szProcessPath, sizeof(szProcessPath) - 1);
-            close(fd);
-        }
-    }
-    if (len <= 0) {
-        snprintf(str, size, "%i", (int)getpid());
-        return true;
-    }
-#endif
-    szProcessPath[len] = 0;
-
-    lpProcessName = strrchr(szProcessPath, '/');
-    lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
-
-    strncpy(str, lpProcessName, size);
-    if (size)
-        str[size - 1] = 0;
-
-    return true;
-}
-
-bool
-GetCurrentDir(char *str, size_t size)
-{
-    char *ret;
-    ret = getcwd(str, size);
-    str[size - 1] = 0;
-    return ret ? true : false;
-}
-
-void
-DebugMessage(const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-    fflush(stdout);
-    vfprintf(stderr, format, ap);
-    va_end(ap);
-}
-
-long long GetTime(void)
-{
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return tv.tv_usec + tv.tv_sec*1000000LL;
-}
-
-void
-Abort(void)
-{
-    exit(0);
-}
-
-
-static void (*gCallback)(void) = NULL;
-
-#define NUM_SIGNALS 16
-
-struct sigaction old_actions[NUM_SIGNALS];
-
-
-/*
- * See also:
- * - http://sourceware.org/git/?p=glibc.git;a=blob;f=debug/segfault.c
- * - http://ggi.cvs.sourceforge.net/viewvc/ggi/ggi-core/libgg/gg/cleanup.c?view=markup
- */
-static void signal_handler(int sig, siginfo_t *info, void *context)
-{
-    static int recursion_count = 0;
-
-    fprintf(stderr, "signal_handler: sig = %i\n", sig);
-
-    if (recursion_count) {
-        fprintf(stderr, "recursion with sig %i\n", sig);
-    } else {
-        if (gCallback) {
-            ++recursion_count;
-            gCallback();
-            --recursion_count;
-        }
-    }
-
-    struct sigaction *old_action;
-    if (sig >= NUM_SIGNALS) {
-        /* This should never happen */
-        fprintf(stderr, "Unexpected signal %i\n", sig);
-        raise(SIGKILL);
-    }
-    old_action = &old_actions[sig];
-
-    if (old_action->sa_flags & SA_SIGINFO) {
-        // Handler is in sa_sigaction
-        old_action->sa_sigaction(sig, info, context);
-    } else {
-        if (old_action->sa_handler == SIG_DFL) {
-            fprintf(stderr, "taking default action for signal %i\n", sig);
-
-#if 1
-            struct sigaction dfl_action;
-            dfl_action.sa_handler = SIG_DFL;
-            sigemptyset (&dfl_action.sa_mask);
-            dfl_action.sa_flags = 0;
-            sigaction(sig, &dfl_action, NULL);
-
-            raise(sig);
-#else
-            raise(SIGKILL);
-#endif
-        } else if (old_action->sa_handler == SIG_IGN) {
-            /* ignore */
-        } else {
-            /* dispatch to handler */
-            old_action->sa_handler(sig);
-        }
-    }
-}
-
-void
-SetExceptionCallback(void (*callback)(void))
-{
-    assert(!gCallback);
-    if (!gCallback) {
-        gCallback = callback;
-
-        struct sigaction new_action;
-        new_action.sa_sigaction = signal_handler;
-        sigemptyset(&new_action.sa_mask);
-        new_action.sa_flags = SA_SIGINFO | SA_RESTART;
-
-
-        for (int sig = 1; sig < NUM_SIGNALS; ++sig) {
-            // SIGKILL and SIGSTOP can't be handled
-            if (sig != SIGKILL && sig != SIGSTOP) {
-                if (sigaction(sig,  NULL, &old_actions[sig]) >= 0) {
-                    sigaction(sig,  &new_action, NULL);
-                }
-            }
-        }
-    }
-}
-
-void
-ResetExceptionCallback(void)
-{
-    gCallback = NULL;
-}
-
-} /* namespace OS */
-
diff --git a/os_win32.cpp b/os_win32.cpp
deleted file mode 100644 (file)
index 587503c..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-#include <windows.h>
-#include <assert.h>
-#include <signal.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "os.hpp"
-
-
-namespace OS {
-
-
-/* 
- * Trick from http://locklessinc.com/articles/pthreads_on_windows/
- */
-static CRITICAL_SECTION
-CriticalSection = {
-    (PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0
-};
-
-
-void
-AcquireMutex(void)
-{
-    EnterCriticalSection(&CriticalSection); 
-}
-
-
-void
-ReleaseMutex(void)
-{
-    LeaveCriticalSection(&CriticalSection); 
-}
-
-
-bool
-GetProcessName(char *str, size_t size)
-{
-    char szProcessPath[PATH_MAX];
-    char *lpProcessName;
-    char *lpProcessExt;
-
-    GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
-
-    lpProcessName = strrchr(szProcessPath, '\\');
-    lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
-
-    lpProcessExt = strrchr(lpProcessName, '.');
-    if (lpProcessExt) {
-        *lpProcessExt = '\0';
-    }
-
-    strncpy(str, lpProcessName, size);
-
-    return true;
-}
-
-bool
-GetCurrentDir(char *str, size_t size)
-{
-    DWORD ret;
-    ret = GetCurrentDirectoryA(size, str);
-    str[size - 1] = 0;
-    return ret == 0 ? false : true;
-}
-
-void
-DebugMessage(const char *format, ...)
-{
-    char buf[4096];
-
-    va_list ap;
-    va_start(ap, format);
-    fflush(stdout);
-    vsnprintf(buf, sizeof buf, format, ap);
-    va_end(ap);
-
-    OutputDebugStringA(buf);
-
-    /*
-     * Also write the message to stderr, when a debugger is not present (to
-     * avoid duplicate messages in command line debuggers).
-     */
-#if _WIN32_WINNT > 0x0400
-    if (!IsDebuggerPresent()) {
-        fflush(stdout);
-        fputs(buf, stderr);
-        fflush(stderr);
-    }
-#endif
-}
-
-long long GetTime(void)
-{
-    static LARGE_INTEGER frequency;
-    LARGE_INTEGER counter;
-    if (!frequency.QuadPart)
-        QueryPerformanceFrequency(&frequency);
-    QueryPerformanceCounter(&counter);
-    return counter.QuadPart*1000000LL/frequency.QuadPart;
-}
-
-void
-Abort(void)
-{
-#ifndef NDEBUG
-    DebugBreak();
-#else
-    ExitProcess(0);
-#endif
-}
-
-
-static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter = NULL;
-static void (*gCallback)(void) = NULL;
-
-static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
-{
-    if (gCallback) {
-        gCallback();
-    }
-
-       if (prevExceptionFilter) {
-               return prevExceptionFilter(pExceptionInfo);
-    } else {
-               return EXCEPTION_CONTINUE_SEARCH;
-    }
-}
-
-void
-SetExceptionCallback(void (*callback)(void))
-{
-    assert(!gCallback);
-
-    if (!gCallback) {
-        gCallback = callback;
-
-        assert(!prevExceptionFilter);
-        prevExceptionFilter = SetUnhandledExceptionFilter(UnhandledExceptionFilter);
-    }
-}
-
-void
-ResetExceptionCallback(void)
-{
-    gCallback = NULL;
-}
-
-
-} /* namespace OS */
diff --git a/trace_file.cpp b/trace_file.cpp
deleted file mode 100644 (file)
index f48c1aa..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Zack Rusin
- * 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.
- *
- **************************************************************************/
-
-
-#include "trace_file.hpp"
-
-#include "trace_snappyfile.hpp"
-
-#include <assert.h>
-#include <string.h>
-
-#include <zlib.h>
-
-#include "os.hpp"
-
-#include <iostream>
-
-using namespace Trace;
-
-
-File::File(const std::string &filename,
-           File::Mode mode)
-    : m_mode(mode),
-      m_isOpened(false)
-{
-    if (!filename.empty()) {
-        open(filename, m_mode);
-    }
-}
-
-File::~File()
-{
-    close();
-}
-
-
-void File::setCurrentOffset(const File::Offset &offset)
-{
-    assert(0);
-}
-
-bool File::isZLibCompressed(const std::string &filename)
-{
-    std::fstream stream(filename.c_str(),
-                        std::fstream::binary | std::fstream::in);
-    if (!stream.is_open())
-        return false;
-
-    unsigned char byte1, byte2;
-    stream >> byte1;
-    stream >> byte2;
-    stream.close();
-
-    return (byte1 == 0x1f && byte2 == 0x8b);
-}
-
-
-bool File::isSnappyCompressed(const std::string &filename)
-{
-    std::fstream stream(filename.c_str(),
-                        std::fstream::binary | std::fstream::in);
-    if (!stream.is_open())
-        return false;
-
-    unsigned char byte1, byte2;
-    stream >> byte1;
-    stream >> byte2;
-    stream.close();
-
-    return (byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
-}
-
-typedef struct gz_stream {
-    z_stream stream;
-    int      z_err;   /* error code for last stream operation */
-    int      z_eof;   /* set if end of input file */
-    FILE     *file;   /* .gz file */
-} gz_dummy_stream;
-
-ZLibFile::ZLibFile(const std::string &filename,
-                   File::Mode mode)
-    : File(filename, mode),
-      m_gzFile(NULL)
-{
-}
-
-ZLibFile::~ZLibFile()
-{
-}
-
-bool ZLibFile::rawOpen(const std::string &filename, File::Mode mode)
-{
-    m_gzFile = gzopen(filename.c_str(),
-                      (mode == File::Write) ? "wb" : "rb");
-
-    if (mode == File::Read && m_gzFile) {
-        //XXX: unfortunately zlib doesn't support
-        //     SEEK_END or we could've done:
-        //m_endOffset = gzseek(m_gzFile, 0, SEEK_END);
-        //gzrewind(m_gzFile);
-        gz_dummy_stream *stream = (gz_dummy_stream *)m_gzFile;
-        long loc = ftell(stream->file);
-        fseek(stream->file,0,SEEK_END);
-        m_endOffset = ftell(stream->file);
-        fseek(stream->file, loc, SEEK_SET);
-    }
-
-    return m_gzFile != NULL;
-}
-
-bool ZLibFile::rawWrite(const void *buffer, size_t length)
-{
-    return gzwrite(m_gzFile, buffer, length) != -1;
-}
-
-bool ZLibFile::rawRead(void *buffer, size_t length)
-{
-    return gzread(m_gzFile, buffer, length) != -1;
-}
-
-int ZLibFile::rawGetc()
-{
-    return gzgetc(m_gzFile);
-}
-
-void ZLibFile::rawClose()
-{
-    if (m_gzFile) {
-        gzclose(m_gzFile);
-        m_gzFile = NULL;
-    }
-}
-
-void ZLibFile::rawFlush()
-{
-    gzflush(m_gzFile, Z_SYNC_FLUSH);
-}
-
-File::Offset ZLibFile::currentOffset()
-{
-    return File::Offset(gztell(m_gzFile));
-}
-
-bool ZLibFile::supportsOffsets() const
-{
-    return false;
-}
-
-bool ZLibFile::rawSkip(size_t)
-{
-    return false;
-}
-
-int ZLibFile::rawPercentRead()
-{
-    gz_dummy_stream *stream = (gz_dummy_stream *)m_gzFile;
-    return 100 * (ftell(stream->file) / m_endOffset);
-}
diff --git a/trace_file.hpp b/trace_file.hpp
deleted file mode 100644 (file)
index 4b1b70d..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Zack Rusin
- * 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 TRACE_FILE_HPP
-#define TRACE_FILE_HPP
-
-#include <string>
-#include <fstream>
-#include <stdint.h>
-
-namespace Trace {
-
-class File {
-public:
-    enum Mode {
-        Read,
-        Write
-    };
-    struct Offset {
-        Offset(uint64_t _chunk = 0, uint32_t _offsetInChunk = 0)
-            : chunk(_chunk),
-              offsetInChunk(_offsetInChunk)
-        {}
-        uint64_t chunk;
-        uint32_t offsetInChunk;
-    };
-
-public:
-    static bool isZLibCompressed(const std::string &filename);
-    static bool isSnappyCompressed(const std::string &filename);
-public:
-    File(const std::string &filename = std::string(),
-         File::Mode mode = File::Read);
-    virtual ~File();
-
-    bool isOpened() const;
-    File::Mode mode() const;
-
-    bool open(const std::string &filename, File::Mode mode);
-    bool write(const void *buffer, size_t length);
-    bool read(void *buffer, size_t length);
-    void close();
-    void flush(void);
-    int getc();
-    bool skip(size_t length);
-    int percentRead();
-
-    virtual bool supportsOffsets() const = 0;
-    virtual File::Offset currentOffset() = 0;
-    virtual void setCurrentOffset(const File::Offset &offset);
-protected:
-    virtual bool rawOpen(const std::string &filename, File::Mode mode) = 0;
-    virtual bool rawWrite(const void *buffer, size_t length) = 0;
-    virtual bool rawRead(void *buffer, size_t length) = 0;
-    virtual int rawGetc() = 0;
-    virtual void rawClose() = 0;
-    virtual void rawFlush() = 0;
-    virtual bool rawSkip(size_t length) = 0;
-    virtual int rawPercentRead() = 0;
-
-protected:
-    File::Mode m_mode;
-    bool m_isOpened;
-};
-
-inline bool File::isOpened() const
-{
-    return m_isOpened;
-}
-
-inline File::Mode File::mode() const
-{
-    return m_mode;
-}
-
-inline bool File::open(const std::string &filename, File::Mode mode)
-{
-    if (m_isOpened) {
-        close();
-    }
-    m_isOpened = rawOpen(filename, mode);
-    m_mode = mode;
-
-    return m_isOpened;
-}
-
-inline bool File::write(const void *buffer, size_t length)
-{
-    if (!m_isOpened || m_mode != File::Write) {
-        return false;
-    }
-    return rawWrite(buffer, length);
-}
-
-inline bool File::read(void *buffer, size_t length)
-{
-    if (!m_isOpened || m_mode != File::Read) {
-        return false;
-    }
-    return rawRead(buffer, length);
-}
-
-inline int File::percentRead()
-{
-    if (!m_isOpened || m_mode != File::Read) {
-        return 0;
-    }
-    return rawPercentRead();
-}
-
-inline void File::close()
-{
-    if (m_isOpened) {
-        rawClose();
-        m_isOpened = false;
-    }
-}
-
-inline void File::flush(void)
-{
-    if (m_mode == File::Write) {
-        rawFlush();
-    }
-}
-
-inline int File::getc()
-{
-    if (!m_isOpened || m_mode != File::Read) {
-        return -1;
-    }
-    return rawGetc();
-}
-
-inline bool File::skip(size_t length)
-{
-    if (!m_isOpened || m_mode != File::Read) {
-        return false;
-    }
-    return rawSkip(length);
-}
-
-class ZLibFile : public File {
-public:
-    ZLibFile(const std::string &filename = std::string(),
-             File::Mode mode = File::Read);
-    virtual ~ZLibFile();
-
-
-    virtual bool supportsOffsets() const;
-    virtual File::Offset currentOffset();
-protected:
-    virtual bool rawOpen(const std::string &filename, File::Mode mode);
-    virtual bool rawWrite(const void *buffer, size_t length);
-    virtual bool rawRead(void *buffer, size_t length);
-    virtual int rawGetc();
-    virtual void rawClose();
-    virtual void rawFlush();
-    virtual bool rawSkip(size_t length);
-    virtual int  rawPercentRead();
-private:
-    void *m_gzFile;
-    double m_endOffset;
-};
-
-inline bool
-operator<(const File::Offset &one, const File::Offset &two)
-{
-    return one.chunk < two.chunk ||
-            (one.chunk == two.chunk && one.offsetInChunk < two.offsetInChunk);
-}
-
-inline bool
-operator==(const File::Offset &one, const File::Offset &two)
-{
-    return one.chunk == two.chunk &&
-            one.offsetInChunk == two.offsetInChunk;
-}
-
-inline bool
-operator>=(const File::Offset &one, const File::Offset &two)
-{
-    return one.chunk > two.chunk ||
-            (one.chunk == two.chunk && one.offsetInChunk >= two.offsetInChunk);
-}
-
-inline bool
-operator>(const File::Offset &one, const File::Offset &two)
-{
-    return two < one;
-}
-
-inline bool
-operator<=(const File::Offset &one, const File::Offset &two)
-{
-    return two >= one;
-}
-
-
-}
-
-#endif
diff --git a/trace_format.hpp b/trace_format.hpp
deleted file mode 100644 (file)
index a8ee5eb..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-/*
- * Trace binary format.
- *
- * Grammar:
- *
- *   trace = event* EOF
- *
- *   event = EVENT_ENTER call_sig call_detail+
- *         | EVENT_LEAVE call_no call_detail+
- *
- *   call_sig = sig_id ( name arg_names )?
- *
- *   call_detail = ARG index value
- *               | RET value
- *               | END
- *
- *   value = NULL
- *         | FALSE
- *         | TRUE
- *         | SINT int
- *         | UINT int
- *         | FLOAT float
- *         | DOUBLE double
- *         | STRING string
- *         | BLOB string
- *         | ENUM enum_sig
- *         | BITMASK bitmask_sig value
- *         | ARRAY length value+
- *         | STRUCT struct_sig value+
- *         | OPAQUE int
- *
- *   call_sig = id name arg_name*
- *            | id
- *
- *   enum_sig = id name value
- *            | id
- *
- *   bitmask_sig = id count (name value)+
- *               | id
- *
- *   string = length (BYTE)*
- *
- */
-
-#ifndef _TRACE_FORMAT_HPP_
-#define _TRACE_FORMAT_HPP_
-
-namespace Trace {
-
-#define TRACE_VERSION 1
-
-enum Event {
-    EVENT_ENTER = 0,
-    EVENT_LEAVE,
-};
-
-enum CallDetail {
-    CALL_END = 0,
-    CALL_ARG,
-    CALL_RET,
-    CALL_THREAD,
-};
-
-enum Type {
-    TYPE_NULL = 0,
-    TYPE_FALSE,
-    TYPE_TRUE,
-    TYPE_SINT,
-    TYPE_UINT,
-    TYPE_FLOAT,
-    TYPE_DOUBLE,
-    TYPE_STRING, // Null terminated, human readible string
-    TYPE_BLOB, // Block of bytes
-    TYPE_ENUM,
-    TYPE_BITMASK,
-    TYPE_ARRAY,
-    TYPE_STRUCT,
-    TYPE_OPAQUE,
-};
-
-
-} /* namespace Trace */
-
-#endif /* _TRACE_FORMAT_HPP_ */
diff --git a/trace_loader.cpp b/trace_loader.cpp
deleted file mode 100644 (file)
index c14d815..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-#include "trace_loader.hpp"
-
-
-using namespace Trace;
-
-Loader::Loader()
-    : m_frameMarker(FrameMarker_SwapBuffers)
-{
-}
-
-Loader::~Loader()
-{
-    close();
-}
-
-Loader::FrameMarker Loader::frameMarker() const
-{
-    return m_frameMarker;
-}
-
-void Loader::setFrameMarker(Loader::FrameMarker marker)
-{
-    m_frameMarker = marker;
-}
-
-int Loader::numberOfFrames() const
-{
-    return m_frameBookmarks.size();
-}
-
-int Loader::numberOfCallsInFrame(int frameIdx) const
-{
-    if (frameIdx > m_frameBookmarks.size()) {
-        return 0;
-    }
-    FrameBookmarks::const_iterator itr =
-        m_frameBookmarks.find(frameIdx);
-    return itr->second.numberOfCalls;
-}
-
-bool Loader::open(const char *filename)
-{
-    if (!m_parser.open(filename)) {
-        std::cerr << "error: failed to open " << filename << "\n";
-        return false;
-    }
-    if (!m_parser.supportsOffsets()) {
-        std::cerr << "error: " <<filename<< " doesn't support seeking "
-                  << "\n";
-        return false;
-    }
-
-    Trace::Call *call;
-    ParseBookmark startBookmark;
-    int numOfFrames = 0;
-    int numOfCalls = 0;
-    int lastPercentReport = 0;
-
-    m_parser.getBookmark(startBookmark);
-
-    while ((call = m_parser.scan_call())) {
-        ++numOfCalls;
-
-        if (isCallAFrameMarker(call)) {
-            FrameBookmark frameBookmark(startBookmark);
-            frameBookmark.numberOfCalls = numOfCalls;
-
-            m_frameBookmarks[numOfFrames] = frameBookmark;
-            ++numOfFrames;
-
-            if (m_parser.percentRead() - lastPercentReport >= 5) {
-                std::cerr << "\tPercent scanned = "
-                          << m_parser.percentRead()
-                          << "..."<<std::endl;
-                lastPercentReport = m_parser.percentRead();
-            }
-            
-            m_parser.getBookmark(startBookmark);
-            numOfCalls = 0;
-        }
-        //call->dump(std::cout, color);
-        delete call;
-    }
-    return true;
-}
-
-void Loader::close()
-{
-    m_parser.close();
-}
-
-bool Loader::isCallAFrameMarker(const Trace::Call *call) const
-{
-    std::string name = call->name();
-
-    switch (m_frameMarker) {
-    case FrameMarker_SwapBuffers:
-        return  name.find("SwapBuffers") != std::string::npos ||
-                name == "CGLFlushDrawable" ||
-                name == "glFrameTerminatorGREMEDY";
-        break;
-    case FrameMarker_Flush:
-        return name == "glFlush";
-        break;
-    case FrameMarker_Finish:
-        return name == "glFinish";
-        break;
-    case FrameMarker_Clear:
-        return name == "glClear";
-        break;
-    }
-    return false;
-}
-
-std::vector<Trace::Call *> Loader::frame(int idx)
-{
-    int numOfCalls = numberOfCallsInFrame(idx);
-    if (numOfCalls) {
-        const FrameBookmark &frameBookmark = m_frameBookmarks[idx];
-        std::vector<Trace::Call*> calls(numOfCalls);
-        m_parser.setBookmark(frameBookmark.start);
-
-        Trace::Call *call;
-        int parsedCalls = 0;
-        while ((call = m_parser.parse_call())) {
-
-            calls[parsedCalls] = call;
-            ++parsedCalls;
-
-            if (isCallAFrameMarker(call)) {
-                break;
-            }
-
-        }
-        assert(parsedCalls == numOfCalls);
-        return calls;
-    }
-    return std::vector<Trace::Call*>();
-}
diff --git a/trace_loader.hpp b/trace_loader.hpp
deleted file mode 100644 (file)
index 9f74a9b..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef TRACE_LOADER_HPP
-#define TRACE_LOADER_HPP
-
-#include "trace_file.hpp"
-#include "trace_parser.hpp"
-
-#include <string>
-#include <map>
-#include <queue>
-#include <vector>
-
-namespace Trace  {
-
-class Frame;
-
-class Loader
-{
-public:
-    enum FrameMarker {
-        FrameMarker_SwapBuffers,
-        FrameMarker_Flush,
-        FrameMarker_Finish,
-        FrameMarker_Clear
-    };
-public:
-    Loader();
-    ~Loader();
-
-    Loader::FrameMarker frameMarker() const;
-    void setFrameMarker(Loader::FrameMarker marker);
-
-    int numberOfFrames() const;
-    int numberOfCallsInFrame(int frameIdx) const;
-
-    bool open(const char *filename);
-    void close();
-
-    std::vector<Trace::Call*> frame(int idx);
-
-private:
-    struct FrameBookmark {
-        FrameBookmark()
-            : numberOfCalls(0)
-        {}
-        FrameBookmark(const ParseBookmark &s)
-            : start(s),
-              numberOfCalls(0)
-        {}
-
-        ParseBookmark start;
-        int numberOfCalls;
-    };
-    bool isCallAFrameMarker(const Trace::Call *call) const;
-
-private:
-    Trace::Parser m_parser;
-    FrameMarker m_frameMarker;
-
-    typedef std::map<int, FrameBookmark> FrameBookmarks;
-    FrameBookmarks m_frameBookmarks;
-};
-
-}
-
-#endif // TRACE_LOADER_HPP
diff --git a/trace_local_writer.cpp b/trace_local_writer.cpp
deleted file mode 100644 (file)
index ea6c111..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2007-2011 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.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "os.hpp"
-#include "trace_file.hpp"
-#include "trace_writer.hpp"
-#include "trace_format.hpp"
-
-
-namespace Trace {
-
-
-static void exceptionCallback(void)
-{
-    OS::DebugMessage("apitrace: flushing trace due to an exception\n");
-    localWriter.flush();
-}
-
-
-LocalWriter::LocalWriter() :
-    acquired(0)
-{}
-
-LocalWriter::~LocalWriter()
-{
-    OS::ResetExceptionCallback();
-}
-
-void
-LocalWriter::open(void) {
-
-    static unsigned dwCounter = 0;
-
-    const char *szExtension = "trace";
-    char szFileName[PATH_MAX];
-    const char *lpFileName;
-
-    lpFileName = getenv("TRACE_FILE");
-    if (lpFileName) {
-        strncpy(szFileName, lpFileName, PATH_MAX);
-    }
-    else {
-        char szProcessName[PATH_MAX];
-        char szCurrentDir[PATH_MAX];
-        OS::GetProcessName(szProcessName, PATH_MAX);
-        OS::GetCurrentDir(szCurrentDir, PATH_MAX);
-
-        for (;;) {
-            FILE *file;
-
-            if (dwCounter)
-                snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
-            else
-                snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
-
-            file = fopen(szFileName, "rb");
-            if (file == NULL)
-                break;
-
-            fclose(file);
-
-            ++dwCounter;
-        }
-    }
-
-    OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
-
-    Writer::open(szFileName);
-
-    OS::SetExceptionCallback(exceptionCallback);
-
-#if 0
-    // For debugging the exception handler
-    *((int *)0) = 0;
-#endif
-}
-
-unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
-    OS::AcquireMutex();
-    ++acquired;
-
-    if (!m_file->isOpened()) {
-        open();
-    }
-
-    return Writer::beginEnter(sig);
-}
-
-void LocalWriter::endEnter(void) {
-    Writer::endEnter();
-    --acquired;
-    OS::ReleaseMutex();
-}
-
-void LocalWriter::beginLeave(unsigned call) {
-    OS::AcquireMutex();
-    ++acquired;
-    Writer::beginLeave(call);
-}
-
-void LocalWriter::endLeave(void) {
-    Writer::endLeave();
-    --acquired;
-    OS::ReleaseMutex();
-}
-
-void LocalWriter::flush(void) {
-    /*
-     * Do nothing if the mutex is already acquired (e.g., if a segfault happen
-     * while writing the file) to prevent dead-lock.
-     */
-
-    if (!acquired) {
-        OS::AcquireMutex();
-        if (m_file->isOpened()) {
-            m_file->flush();
-        }
-        OS::ReleaseMutex();
-    }
-}
-
-
-LocalWriter localWriter;
-
-
-} /* namespace Trace */
-
diff --git a/trace_model.cpp b/trace_model.cpp
deleted file mode 100644 (file)
index 306b9e7..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-
-#include "formatter.hpp"
-#include "trace_model.hpp"
-
-
-namespace Trace {
-
-
-Call::~Call() {
-    for (unsigned i = 0; i < args.size(); ++i) {
-        delete args[i];
-    }
-
-    if (ret) {
-        delete ret;
-    }
-}
-
-
-String::~String() {
-    delete [] value;
-}
-
-
-Struct::~Struct() {
-    for (std::vector<Value *>::iterator it = members.begin(); it != members.end(); ++it) {
-        delete *it;
-    }
-}
-
-
-Array::~Array() {
-    for (std::vector<Value *>::iterator it = values.begin(); it != values.end(); ++it) {
-        delete *it;
-    }
-}
-
-Blob::~Blob() {
-    // Blobs are often bound and referred during many calls, so we can't delete
-    // them here in that case.
-    //
-    // Once bound there is no way to know when they were unbound, which
-    // effectively means we have to leak them.  A better solution would be to
-    // keep a list of bound pointers, and defer the destruction to when the
-    // trace in question has been fully processed.
-    if (!bound) {
-        delete [] buf;
-    }
-}
-
-
-// bool cast
-bool Null   ::toBool(void) const { return false; }
-bool Bool   ::toBool(void) const { return value; }
-bool SInt   ::toBool(void) const { return value != 0; }
-bool UInt   ::toBool(void) const { return value != 0; }
-bool Float  ::toBool(void) const { return value != 0; }
-bool String ::toBool(void) const { return true; }
-bool Enum   ::toBool(void) const { return sig->value != 0; }
-bool Struct ::toBool(void) const { return true; }
-bool Array  ::toBool(void) const { return true; }
-bool Blob   ::toBool(void) const { return true; }
-bool Pointer::toBool(void) const { return value != 0; }
-
-
-// signed integer cast
-signed long long Value  ::toSInt(void) const { assert(0); return 0; }
-signed long long Null   ::toSInt(void) const { return 0; }
-signed long long Bool   ::toSInt(void) const { return static_cast<signed long long>(value); }
-signed long long SInt   ::toSInt(void) const { return value; }
-signed long long UInt   ::toSInt(void) const { assert(static_cast<signed long long>(value) >= 0); return static_cast<signed long long>(value); }
-signed long long Float  ::toSInt(void) const { return static_cast<signed long long>(value); }
-signed long long Enum   ::toSInt(void) const { return sig->value; }
-
-
-// unsigned integer cast
-unsigned long long Value  ::toUInt(void) const { assert(0); return 0; }
-unsigned long long Null   ::toUInt(void) const { return 0; }
-unsigned long long Bool   ::toUInt(void) const { return static_cast<unsigned long long>(value); }
-unsigned long long SInt   ::toUInt(void) const { assert(value >= 0); return static_cast<signed long long>(value); }
-unsigned long long UInt   ::toUInt(void) const { return value; }
-unsigned long long Float  ::toUInt(void) const { return static_cast<unsigned long long>(value); }
-unsigned long long Enum   ::toUInt(void) const { assert(sig->value >= 0); return sig->value; }
-
-
-// floating point cast
-float Value  ::toFloat(void) const { assert(0); return 0; }
-float Null   ::toFloat(void) const { return 0; }
-float Bool   ::toFloat(void) const { return static_cast<float>(value); }
-float SInt   ::toFloat(void) const { return static_cast<float>(value); }
-float UInt   ::toFloat(void) const { return static_cast<float>(value); }
-float Float  ::toFloat(void) const { return value; }
-float Enum   ::toFloat(void) const { return static_cast<float>(sig->value); }
-
-
-// floating point cast
-double Value  ::toDouble(void) const { assert(0); return 0; }
-double Null   ::toDouble(void) const { return 0; }
-double Bool   ::toDouble(void) const { return static_cast<double>(value); }
-double SInt   ::toDouble(void) const { return static_cast<double>(value); }
-double UInt   ::toDouble(void) const { return static_cast<double>(value); }
-double Float  ::toDouble(void) const { return value; }
-double Enum   ::toDouble(void) const { return static_cast<double>(sig->value); }
-
-
-// pointer cast
-void * Value  ::toPointer(void) const { assert(0); return NULL; }
-void * Null   ::toPointer(void) const { return NULL; }
-void * Blob   ::toPointer(void) const { return buf; }
-void * Pointer::toPointer(void) const { return (void *)value; }
-
-void * Value  ::toPointer(bool bind) { assert(0); return NULL; }
-void * Null   ::toPointer(bool bind) { return NULL; }
-void * Blob   ::toPointer(bool bind) { if (bind) bound = true; return buf; }
-void * Pointer::toPointer(bool bind) { return (void *)value; }
-
-
-// pointer cast
-unsigned long long Value  ::toUIntPtr(void) const { assert(0); return 0; }
-unsigned long long Null   ::toUIntPtr(void) const { return 0; }
-unsigned long long Pointer::toUIntPtr(void) const { return value; }
-
-
-// string cast
-const char * Value ::toString(void) const { assert(0); return NULL; }
-const char * Null  ::toString(void) const { return NULL; }
-const char * String::toString(void) const { return value; }
-
-
-// virtual Value::visit()
-void Null   ::visit(Visitor &visitor) { visitor.visit(this); }
-void Bool   ::visit(Visitor &visitor) { visitor.visit(this); }
-void SInt   ::visit(Visitor &visitor) { visitor.visit(this); }
-void UInt   ::visit(Visitor &visitor) { visitor.visit(this); }
-void Float  ::visit(Visitor &visitor) { visitor.visit(this); }
-void String ::visit(Visitor &visitor) { visitor.visit(this); }
-void Enum   ::visit(Visitor &visitor) { visitor.visit(this); }
-void Bitmask::visit(Visitor &visitor) { visitor.visit(this); }
-void Struct ::visit(Visitor &visitor) { visitor.visit(this); }
-void Array  ::visit(Visitor &visitor) { visitor.visit(this); }
-void Blob   ::visit(Visitor &visitor) { visitor.visit(this); }
-void Pointer::visit(Visitor &visitor) { visitor.visit(this); }
-
-
-void Visitor::visit(Null *) { assert(0); }
-void Visitor::visit(Bool *) { assert(0); }
-void Visitor::visit(SInt *) { assert(0); }
-void Visitor::visit(UInt *) { assert(0); }
-void Visitor::visit(Float *) { assert(0); }
-void Visitor::visit(String *) { assert(0); }
-void Visitor::visit(Enum *node) { assert(0); }
-void Visitor::visit(Bitmask *node) { visit(static_cast<UInt *>(node)); }
-void Visitor::visit(Struct *) { assert(0); }
-void Visitor::visit(Array *) { assert(0); }
-void Visitor::visit(Blob *) { assert(0); }
-void Visitor::visit(Pointer *) { assert(0); }
-
-
-class Dumper : public Visitor
-{
-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;
-
-public:
-    Dumper(std::ostream &_os, bool color) : os(_os) {
-        formatter = Formatter::defaultFormatter(color);
-        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() {
-        delete normal;
-        delete bold;
-        delete italic;
-        delete red;
-        delete pointer;
-        delete literal;
-        delete formatter;
-    }
-
-    void visit(Null *) {
-        os << "NULL";
-    }
-
-    void visit(Bool *node) {
-        os << literal << (node->value ? "true" : "false") << normal;
-    }
-
-    void visit(SInt *node) {
-        os << literal << node->value << normal;
-    }
-
-    void visit(UInt *node) {
-        os << literal << node->value << normal;
-    }
-
-    void visit(Float *node) {
-        os << literal << node->value << normal;
-    }
-
-    void visit(String *node) {
-        os << literal << "\"";
-        for (const char *it = node->value; *it; ++it) {
-            unsigned char c = (unsigned char) *it;
-            if (c == '\"')
-                os << "\\\"";
-            else if (c == '\\')
-                os << "\\\\";
-            else if (c >= 0x20 && c <= 0x7e)
-                os << c;
-            else if (c == '\t') {
-                os << "\t";
-            } else if (c == '\r') {
-                // Ignore carriage-return
-            } else if (c == '\n') {
-                // Reset formatting so that it looks correct with 'less -R'
-                os << normal << '\n' << literal;
-            } else {
-                unsigned octal0 = c & 0x7;
-                unsigned octal1 = (c >> 3) & 0x7;
-                unsigned octal2 = (c >> 3) & 0x7;
-                os << "\\";
-                if (octal2)
-                    os << octal2;
-                if (octal1)
-                    os << octal1;
-                os << octal0;
-            }
-        }
-        os << "\"" << normal;
-    }
-
-    void visit(Enum *node) {
-        os << literal << node->sig->name << normal;
-    }
-
-    void visit(Bitmask *bitmask) {
-        unsigned long long value = bitmask->value;
-        const BitmaskSig *sig = bitmask->sig;
-        bool first = true;
-        for (const BitmaskFlag *it = sig->flags; value != 0 && it != sig->flags + sig->num_flags; ++it) {
-            if ((it->value && (value & it->value) == it->value) ||
-                (!it->value && value == 0)) {
-                if (!first) {
-                    os << " | ";
-                }
-                os << literal << it->name << normal;
-                value &= ~it->value;
-                first = false;
-            }
-        }
-        if (value || first) {
-            if (!first) {
-                os << " | ";
-            }
-            os << literal << "0x" << std::hex << value << std::dec << normal;
-        }
-    }
-
-    void visit(Struct *s) {
-        const char *sep = "";
-        os << "{";
-        for (unsigned i = 0; i < s->members.size(); ++i) {
-            os << sep << italic << s->sig->member_names[i] << normal << " = ";
-            _visit(s->members[i]);
-            sep = ", ";
-        }
-        os << "}";
-    }
-
-    void visit(Array *array) {
-        if (array->values.size() == 1) {
-            os << "&";
-            _visit(array->values[0]);
-        }
-        else {
-            const char *sep = "";
-            os << "{";
-            for (std::vector<Value *>::iterator it = array->values.begin(); it != array->values.end(); ++it) {
-                os << sep;
-                _visit(*it);
-                sep = ", ";
-            }
-            os << "}";
-        }
-    }
-
-    void visit(Blob *blob) {
-        os << pointer << "blob(" << blob->size << ")" << normal;
-    }
-
-    void visit(Pointer *p) {
-        os << pointer << "0x" << std::hex << p->value << std::dec << normal;
-    }
-
-    void visit(Call *call) {
-        const char *sep = "";
-        os << bold << call->sig->name << normal << "(";
-        for (unsigned i = 0; i < call->args.size(); ++i) {
-            os << sep << italic << call->sig->arg_names[i] << normal << " = ";
-            if (call->args[i]) {
-                _visit(call->args[i]);
-            } else {
-               os << "?";
-            }
-            sep = ", ";
-        }
-        os << ")";
-        if (call->ret) {
-            os << " = ";
-            _visit(call->ret);
-        }
-        os << "\n";
-    }
-};
-
-
-void Value::dump(std::ostream &os, bool color) {
-    Dumper d(os, color);
-    visit(d);
-}
-
-
-static Null null;
-
-const Value & Value::operator[](size_t index) const {
-    const Array *array = dynamic_cast<const Array *>(this);
-    if (array) {
-        if (index < array->values.size()) {
-            return *array->values[index];
-        }
-    }
-    return null;
-}
-
-void Call::dump(std::ostream &os, bool color) {
-    Dumper d(os, color);
-    os << no << " ";
-    d.visit(this);
-}
-
-
-} /* namespace Trace */
diff --git a/trace_model.hpp b/trace_model.hpp
deleted file mode 100644 (file)
index a74508e..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-/*
- * Object hierarchy for describing the traces in memory.
- */
-
-#ifndef _TRACE_MODEL_HPP_
-#define _TRACE_MODEL_HPP_
-
-
-#include <assert.h>
-
-#include <map>
-#include <vector>
-#include <iostream>
-
-
-namespace Trace {
-
-
-typedef unsigned Id;
-
-
-struct FunctionSig {
-    Id id;
-    const char *name;
-    unsigned num_args;
-    const char **arg_names;
-};
-
-
-struct StructSig {
-    Id id;
-    const char *name;
-    unsigned num_members;
-    const char **member_names;
-};
-
-
-struct EnumSig {
-    Id id;
-    const char *name;
-    signed long long value;
-};
-
-
-struct BitmaskFlag {
-    const char *name;
-    unsigned long long value;
-};
-
-
-struct BitmaskSig {
-    Id id;
-    unsigned num_flags;
-    const BitmaskFlag *flags;
-};
-
-
-class Visitor;
-
-
-class Value
-{
-public:
-    virtual ~Value() {}
-    virtual void visit(Visitor &visitor) = 0;
-
-    virtual bool toBool(void) const = 0;
-    virtual signed long long toSInt(void) const;
-    virtual unsigned long long toUInt(void) const;
-    virtual float toFloat(void) const;
-    virtual double toDouble(void) const;
-
-    virtual void *toPointer(void) const;
-    virtual void *toPointer(bool bind);
-    virtual unsigned long long toUIntPtr(void) const;
-    virtual const char *toString(void) const;
-
-    const Value & operator[](size_t index) const;
-
-    void dump(std::ostream &os, bool color=true);
-};
-
-
-class Null : public Value
-{
-public:
-    bool toBool(void) const;
-    signed long long toSInt(void) const;
-    unsigned long long toUInt(void) const;
-    virtual float toFloat(void) const;
-    virtual double toDouble(void) const;
-    void *toPointer(void) const;
-    void *toPointer(bool bind);
-    unsigned long long toUIntPtr(void) const;
-    const char *toString(void) const;
-    void visit(Visitor &visitor);
-};
-
-
-class Bool : public Value
-{
-public:
-    Bool(bool _value) : value(_value) {}
-
-    bool toBool(void) const;
-    signed long long toSInt(void) const;
-    unsigned long long toUInt(void) const;
-    virtual float toFloat(void) const;
-    virtual double toDouble(void) const;
-    void visit(Visitor &visitor);
-
-    bool value;
-};
-
-
-class SInt : public Value
-{
-public:
-    SInt(signed long long _value) : value(_value) {}
-
-    bool toBool(void) const;
-    signed long long toSInt(void) const;
-    unsigned long long toUInt(void) const;
-    virtual float toFloat(void) const;
-    virtual double toDouble(void) const;
-    void visit(Visitor &visitor);
-
-    signed long long value;
-};
-
-
-class UInt : public Value
-{
-public:
-    UInt(unsigned long long _value) : value(_value) {}
-
-    bool toBool(void) const;
-    signed long long toSInt(void) const;
-    unsigned long long toUInt(void) const;
-    virtual float toFloat(void) const;
-    virtual double toDouble(void) const;
-    void visit(Visitor &visitor);
-
-    unsigned long long value;
-};
-
-
-class Float : public Value
-{
-public:
-    Float(double _value) : value(_value) {}
-
-    bool toBool(void) const;
-    signed long long toSInt(void) const;
-    unsigned long long toUInt(void) const;
-    virtual float toFloat(void) const;
-    virtual double toDouble(void) const;
-    void visit(Visitor &visitor);
-
-    double value;
-};
-
-
-class String : public Value
-{
-public:
-    String(const char * _value) : value(_value) {}
-    ~String();
-
-    bool toBool(void) const;
-    const char *toString(void) const;
-    void visit(Visitor &visitor);
-
-    const char * value;
-};
-
-
-class Enum : public Value
-{
-public:
-    Enum(const EnumSig *_sig) : sig(_sig) {}
-
-    bool toBool(void) const;
-    signed long long toSInt(void) const;
-    unsigned long long toUInt(void) const;
-    virtual float toFloat(void) const;
-    virtual double toDouble(void) const;
-    void visit(Visitor &visitor);
-
-    const EnumSig *sig;
-};
-
-
-class Bitmask : public UInt
-{
-public:
-    Bitmask(const BitmaskSig *_sig, unsigned long long _value) : UInt(_value), sig(_sig) {}
-
-    void visit(Visitor &visitor);
-
-    const BitmaskSig *sig;
-};
-
-
-class Struct : public Value
-{
-public:
-    Struct(StructSig *_sig) : sig(_sig), members(_sig->num_members) { }
-    ~Struct();
-
-    bool toBool(void) const;
-    void visit(Visitor &visitor);
-
-    const StructSig *sig;
-    std::vector<Value *> members;
-};
-
-
-class Array : public Value
-{
-public:
-    Array(size_t len) : values(len) {}
-    ~Array();
-
-    bool toBool(void) const;
-    void visit(Visitor &visitor);
-
-    std::vector<Value *> values;
-};
-
-
-class Blob : public Value
-{
-public:
-    Blob(size_t _size) {
-        size = _size;
-        buf = new char[_size];
-        bound = false;
-    }
-
-    ~Blob();
-
-    bool toBool(void) const;
-    void *toPointer(void) const;
-    void *toPointer(bool bind);
-    void visit(Visitor &visitor);
-
-    size_t size;
-    char *buf;
-    bool bound;
-};
-
-
-class Pointer : public UInt
-{
-public:
-    Pointer(unsigned long long value) : UInt(value) {}
-
-    bool toBool(void) const;
-    void *toPointer(void) const;
-    void *toPointer(bool bind);
-    unsigned long long toUIntPtr(void) const;
-    void visit(Visitor &visitor);
-};
-
-
-class Visitor
-{
-public:
-    virtual void visit(Null *);
-    virtual void visit(Bool *);
-    virtual void visit(SInt *);
-    virtual void visit(UInt *);
-    virtual void visit(Float *);
-    virtual void visit(String *);
-    virtual void visit(Enum *);
-    virtual void visit(Bitmask *);
-    virtual void visit(Struct *);
-    virtual void visit(Array *);
-    virtual void visit(Blob *);
-    virtual void visit(Pointer *);
-
-protected:
-    inline void _visit(Value *value) {
-        if (value) { 
-            value->visit(*this); 
-        }
-    }
-};
-
-
-inline std::ostream & operator <<(std::ostream &os, Value *value) {
-    if (value) {
-        value->dump(os);
-    }
-    return os;
-}
-
-
-class Call
-{
-public:
-    unsigned no;
-    const FunctionSig *sig;
-    std::vector<Value *> args;
-    Value *ret;
-
-    Call(FunctionSig *_sig) : sig(_sig), args(_sig->num_args), ret(0) { }
-    ~Call();
-
-    inline const char * name(void) const {
-        return sig->name;
-    }
-
-    inline Value & arg(unsigned index) {
-        assert(index < args.size());
-        return *(args[index]);
-    }
-
-    void dump(std::ostream &os, bool color=true);
-};
-
-
-inline std::ostream & operator <<(std::ostream &os, Call &call) {
-    call.dump(os);
-    return os;
-}
-
-
-} /* namespace Trace */
-
-#endif /* _TRACE_MODEL_HPP_ */
diff --git a/trace_model_writer.cpp b/trace_model_writer.cpp
deleted file mode 100644 (file)
index dcfcf86..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * 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.
- *
- **************************************************************************/
-
-
-#include "trace_writer.hpp"
-
-
-namespace Trace {
-
-
-class ModelWriter : public Visitor
-{
-protected:
-    Writer &writer;
-
-public:
-    ModelWriter(Writer &_writer) :
-        writer(_writer) {
-    }
-
-    void visit(Null *) {
-        writer.writeNull();
-    }
-
-    void visit(Bool *node) {
-        writer.writeBool(node->value);
-    }
-
-    void visit(SInt *node) {
-        writer.writeSInt(node->value);
-    }
-
-    void visit(UInt *node) {
-        writer.writeUInt(node->value);
-    }
-
-    void visit(Float *node) {
-        writer.writeFloat(node->value);
-    }
-
-    void visit(String *node) {
-        writer.writeString(node->value);
-    }
-
-    void visit(Enum *node) {
-        writer.writeEnum(node->sig);
-    }
-
-    void visit(Bitmask *node) {
-        writer.writeBitmask(node->sig, node->value);
-    }
-
-    void visit(Struct *node) {
-        writer.beginStruct(node->sig);
-        for (unsigned i = 0; i < node->sig->num_members; ++i) {
-            _visit(node->members[i]);
-        }
-        writer.endStruct();
-    }
-
-    void visit(Array *node) {
-        writer.beginArray(node->values.size());
-        for (std::vector<Value *>::iterator it = node->values.begin(); it != node->values.end(); ++it) {
-            _visit(*it);
-        }
-        writer.endArray();
-    }
-
-    void visit(Blob *node) {
-        writer.writeBlob(node->buf, node->size);
-    }
-
-    void visit(Pointer *node) {
-        writer.writeOpaque((const void *) (size_t) node->value);
-    }
-
-    void visit(Call *call) {
-        unsigned call_no = writer.beginEnter(call->sig);
-        for (unsigned i = 0; i < call->args.size(); ++i) {
-            if (call->args[i]) {
-                writer.beginArg(i);
-                _visit(call->args[i]);
-                writer.endArg();
-            }
-        }
-        writer.endEnter();
-        writer.beginLeave(call_no);
-        if (call->ret) {
-            writer.beginReturn();
-            _visit(call->ret);
-            writer.endReturn();
-        }
-        writer.endLeave();
-    }
-};
-
-
-void Writer::writeCall(Call *call) {
-    ModelWriter visitor(*this);
-    visitor.visit(call);
-}
-
-
-} /* namespace Trace */
-
diff --git a/trace_parser.cpp b/trace_parser.cpp
deleted file mode 100644 (file)
index d7b20d2..0000000
+++ /dev/null
@@ -1,731 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Jose Fonseca
- * 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.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "trace_file.hpp"
-#include "trace_snappyfile.hpp"
-#include "trace_parser.hpp"
-
-
-#define TRACE_VERBOSE 0
-
-
-namespace Trace {
-
-
-Parser::Parser() {
-    file = NULL;
-    next_call_no = 0;
-    version = 0;
-}
-
-
-Parser::~Parser() {
-    close();
-}
-
-
-bool Parser::open(const char *filename) {
-    assert(!file);
-    if (File::isZLibCompressed(filename)) {
-        file = new ZLibFile;
-    } else {
-        file = new SnappyFile;
-    }
-
-    if (!file->open(filename, File::Read)) {
-        return false;
-    }
-
-    version = read_uint();
-    if (version > TRACE_VERSION) {
-        std::cerr << "error: unsupported trace format version " << version << "\n";
-        return false;
-    }
-
-    return true;
-}
-
-template <typename Iter>
-inline void
-deleteAll(Iter begin, Iter end)
-{
-    while (begin != end) {
-        delete *begin;
-        ++begin;
-    }
-}
-
-template <typename Container>
-inline void
-deleteAll(Container &c)
-{
-    deleteAll(c.begin(), c.end());
-    c.clear();
-}
-
-void Parser::close(void) {
-    if (file) {
-        file->close();
-        delete file;
-        file = NULL;
-    }
-
-    deleteAll(calls);
-
-    // Delete all signature data.  Signatures are mere structures which don't
-    // own their own memory, so we need to destroy all data we created here.
-
-    for (FunctionMap::iterator it = functions.begin(); it != functions.end(); ++it) {
-        FunctionSigState *sig = *it;
-        if (sig) {
-            delete [] sig->name;
-            for (unsigned arg = 0; arg < sig->num_args; ++arg) {
-                delete [] sig->arg_names[arg];
-            }
-            delete [] sig->arg_names;
-            delete sig;
-        }
-    }
-    functions.clear();
-
-    for (StructMap::iterator it = structs.begin(); it != structs.end(); ++it) {
-        StructSigState *sig = *it;
-        if (sig) {
-            delete [] sig->name;
-            for (unsigned member = 0; member < sig->num_members; ++member) {
-                delete [] sig->member_names[member];
-            }
-            delete [] sig->member_names;
-            delete sig;
-        }
-    }
-    structs.clear();
-
-    for (EnumMap::iterator it = enums.begin(); it != enums.end(); ++it) {
-        EnumSigState *sig = *it;
-        if (sig) {
-            delete [] sig->name;
-            delete sig;
-        }
-    }
-    enums.clear();
-    
-    for (BitmaskMap::iterator it = bitmasks.begin(); it != bitmasks.end(); ++it) {
-        BitmaskSigState *sig = *it;
-        if (sig) {
-            for (unsigned flag = 0; flag < sig->num_flags; ++flag) {
-                delete [] sig->flags[flag].name;
-            }
-            delete [] sig->flags;
-            delete sig;
-        }
-    }
-    bitmasks.clear();
-}
-
-
-void Parser::getBookmark(ParseBookmark &bookmark) {
-    bookmark.offset = file->currentOffset();
-    bookmark.next_call_no = next_call_no;
-}
-
-
-void Parser::setBookmark(const ParseBookmark &bookmark) {
-    file->setCurrentOffset(bookmark.offset);
-    next_call_no = bookmark.next_call_no;
-    
-    // Simply ignore all pending calls
-    deleteAll(calls);
-}
-
-
-Call *Parser::parse_call(Mode mode) {
-    do {
-        int c = read_byte();
-        switch(c) {
-        case Trace::EVENT_ENTER:
-            parse_enter(mode);
-            break;
-        case Trace::EVENT_LEAVE:
-            return parse_leave(mode);
-        default:
-            std::cerr << "error: unknown event " << c << "\n";
-            exit(1);
-        case -1:
-            for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
-                std::cerr << "warning: incomplete call " << (*it)->name() << "\n";
-                std::cerr << **it << "\n";
-            }
-            return NULL;
-        }
-    } while(true);
-}
-
-
-/**
- * Helper function to lookup an ID in a vector, resizing the vector if it doesn't fit.
- */
-template<class T>
-T *lookup(std::vector<T *> &map, size_t index) {
-    if (index >= map.size()) {
-        map.resize(index + 1);
-        return NULL;
-    } else {
-        return map[index];
-    }
-}
-
-
-FunctionSig *Parser::parse_function_sig(void) {
-    size_t id = read_uint();
-
-    FunctionSigState *sig = lookup(functions, id);
-
-    if (!sig) {
-        /* parse the signature */
-        sig = new FunctionSigState;
-        sig->id = id;
-        sig->name = read_string();
-        sig->num_args = read_uint();
-        const char **arg_names = new const char *[sig->num_args];
-        for (unsigned i = 0; i < sig->num_args; ++i) {
-            arg_names[i] = read_string();
-        }
-        sig->arg_names = arg_names;
-        sig->offset = file->currentOffset();
-        functions[id] = sig;
-    } else if (file->currentOffset() < sig->offset) {
-        /* skip over the signature */
-        skip_string(); /* name */
-        int num_args = read_uint();
-        for (unsigned i = 0; i < num_args; ++i) {
-             skip_string(); /*arg_name*/
-        }
-    }
-
-    assert(sig);
-    return sig;
-}
-
-
-StructSig *Parser::parse_struct_sig() {
-    size_t id = read_uint();
-
-    StructSigState *sig = lookup(structs, id);
-
-    if (!sig) {
-        /* parse the signature */
-        sig = new StructSigState;
-        sig->id = id;
-        sig->name = read_string();
-        sig->num_members = read_uint();
-        const char **member_names = new const char *[sig->num_members];
-        for (unsigned i = 0; i < sig->num_members; ++i) {
-            member_names[i] = read_string();
-        }
-        sig->member_names = member_names;
-        sig->offset = file->currentOffset();
-        structs[id] = sig;
-    } else if (file->currentOffset() < sig->offset) {
-        /* skip over the signature */
-        skip_string(); /* name */
-        unsigned num_members = read_uint();
-        for (unsigned i = 0; i < num_members; ++i) {
-            skip_string(); /* member_name */
-        }
-    }
-
-    assert(sig);
-    return sig;
-}
-
-
-EnumSig *Parser::parse_enum_sig() {
-    size_t id = read_uint();
-
-    EnumSigState *sig = lookup(enums, id);
-
-    if (!sig) {
-        /* parse the signature */
-        sig = new EnumSigState;
-        sig->id = id;
-        sig->name = read_string();
-        Value *value = parse_value();
-        sig->value = value->toSInt();
-        delete value;
-        sig->offset = file->currentOffset();
-        enums[id] = sig;
-    } else if (file->currentOffset() < sig->offset) {
-        /* skip over the signature */
-        skip_string(); /*name*/
-        scan_value();
-    }
-
-    assert(sig);
-    return sig;
-}
-
-
-BitmaskSig *Parser::parse_bitmask_sig() {
-    size_t id = read_uint();
-
-    BitmaskSigState *sig = lookup(bitmasks, id);
-
-    if (!sig) {
-        /* parse the signature */
-        sig = new BitmaskSigState;
-        sig->id = id;
-        sig->num_flags = read_uint();
-        BitmaskFlag *flags = new BitmaskFlag[sig->num_flags];
-        for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) {
-            it->name = read_string();
-            it->value = read_uint();
-            if (it->value == 0 && it != flags) {
-                std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n";
-            }
-        }
-        sig->flags = flags;
-        sig->offset = file->currentOffset();
-        bitmasks[id] = sig;
-    } else if (file->currentOffset() < sig->offset) {
-        /* skip over the signature */
-        int num_flags = read_uint();
-        for (int i = 0; i < num_flags; ++i) {
-            skip_string(); /*name */
-            skip_uint(); /* value */
-        }
-    }
-
-    assert(sig);
-    return sig;
-}
-
-
-void Parser::parse_enter(Mode mode) {
-    FunctionSig *sig = parse_function_sig();
-
-    Call *call = new Call(sig);
-
-    call->no = next_call_no++;
-
-    if (parse_call_details(call, mode)) {
-        calls.push_back(call);
-    } else {
-        delete call;
-    }
-}
-
-
-Call *Parser::parse_leave(Mode mode) {
-    unsigned call_no = read_uint();
-    Call *call = NULL;
-    for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
-        if ((*it)->no == call_no) {
-            call = *it;
-            calls.erase(it);
-            break;
-        }
-    }
-    if (!call) {
-        return NULL;
-    }
-
-    if (parse_call_details(call, mode)) {
-        return call;
-    } else {
-        delete call;
-        return NULL;
-    }
-}
-
-
-bool Parser::parse_call_details(Call *call, Mode mode) {
-    do {
-        int c = read_byte();
-        switch(c) {
-        case Trace::CALL_END:
-            return true;
-        case Trace::CALL_ARG:
-            parse_arg(call, mode);
-            break;
-        case Trace::CALL_RET:
-            call->ret = parse_value(mode);
-            break;
-        default:
-            std::cerr << "error: ("<<call->name()<< ") unknown call detail "
-                      << c << "\n";
-            exit(1);
-        case -1:
-            return false;
-        }
-    } while(true);
-}
-
-
-void Parser::parse_arg(Call *call, Mode mode) {
-    unsigned index = read_uint();
-    Value *value = parse_value(mode);
-    if (value) {
-        if (index >= call->args.size()) {
-            call->args.resize(index + 1);
-        }
-        call->args[index] = value;
-    }
-}
-
-
-Value *Parser::parse_value(void) {
-    int c;
-    Value *value;
-    c = read_byte();
-    switch(c) {
-    case Trace::TYPE_NULL:
-        value = new Null;
-        break;
-    case Trace::TYPE_FALSE:
-        value = new Bool(false);
-        break;
-    case Trace::TYPE_TRUE:
-        value = new Bool(true);
-        break;
-    case Trace::TYPE_SINT:
-        value = parse_sint();
-        break;
-    case Trace::TYPE_UINT:
-        value = parse_uint();
-        break;
-    case Trace::TYPE_FLOAT:
-        value = parse_float();
-        break;
-    case Trace::TYPE_DOUBLE:
-        value = parse_double();
-        break;
-    case Trace::TYPE_STRING:
-        value = parse_string();
-        break;
-    case Trace::TYPE_ENUM:
-        value = parse_enum();
-        break;
-    case Trace::TYPE_BITMASK:
-        value = parse_bitmask();
-        break;
-    case Trace::TYPE_ARRAY:
-        value = parse_array();
-        break;
-    case Trace::TYPE_STRUCT:
-        value = parse_struct();
-        break;
-    case Trace::TYPE_BLOB:
-        value = parse_blob();
-        break;
-    case Trace::TYPE_OPAQUE:
-        value = parse_opaque();
-        break;
-    default:
-        std::cerr << "error: unknown type " << c << "\n";
-        exit(1);
-    case -1:
-        value = NULL;
-        break;
-    }
-#if TRACE_VERBOSE
-    if (value) {
-        std::cerr << "\tVALUE " << value << "\n";
-    }
-#endif
-    return value;
-}
-
-
-void Parser::scan_value(void) {
-    int c = read_byte();
-    switch(c) {
-    case Trace::TYPE_NULL:
-    case Trace::TYPE_FALSE:
-    case Trace::TYPE_TRUE:
-        break;
-    case Trace::TYPE_SINT:
-        scan_sint();
-        break;
-    case Trace::TYPE_UINT:
-        scan_uint();
-        break;
-    case Trace::TYPE_FLOAT:
-        scan_float();
-        break;
-    case Trace::TYPE_DOUBLE:
-        scan_double();
-        break;
-    case Trace::TYPE_STRING:
-        scan_string();
-        break;
-    case Trace::TYPE_ENUM:
-        scan_enum();
-        break;
-    case Trace::TYPE_BITMASK:
-        scan_bitmask();
-        break;
-    case Trace::TYPE_ARRAY:
-        scan_array();
-        break;
-    case Trace::TYPE_STRUCT:
-        scan_struct();
-        break;
-    case Trace::TYPE_BLOB:
-        scan_blob();
-        break;
-    case Trace::TYPE_OPAQUE:
-        scan_opaque();
-        break;
-    default:
-        std::cerr << "error: unknown type " << c << "\n";
-        exit(1);
-    case -1:
-        break;
-    }
-}
-
-
-Value *Parser::parse_sint() {
-    return new SInt(-(signed long long)read_uint());
-}
-
-
-void Parser::scan_sint() {
-    skip_uint();
-}
-
-
-Value *Parser::parse_uint() {
-    return new UInt(read_uint());
-}
-
-
-void Parser::scan_uint() {
-    skip_uint();
-}
-
-
-Value *Parser::parse_float() {
-    float value;
-    file->read(&value, sizeof value);
-    return new Float(value);
-}
-
-
-void Parser::scan_float() {
-    file->skip(sizeof(float));
-}
-
-
-Value *Parser::parse_double() {
-    double value;
-    file->read(&value, sizeof value);
-    return new Float(value);
-}
-
-
-void Parser::scan_double() {
-    file->skip(sizeof(double));
-}
-
-
-Value *Parser::parse_string() {
-    return new String(read_string());
-}
-
-
-void Parser::scan_string() {
-    skip_string();
-}
-
-
-Value *Parser::parse_enum() {
-    EnumSig *sig = parse_enum_sig();
-    return new Enum(sig);
-}
-
-
-void Parser::scan_enum() {
-    parse_enum_sig();
-}
-
-
-Value *Parser::parse_bitmask() {
-    BitmaskSig *sig = parse_bitmask_sig();
-
-    unsigned long long value = read_uint();
-
-    return new Bitmask(sig, value);
-}
-
-
-void Parser::scan_bitmask() {
-    parse_bitmask_sig();
-    skip_uint(); /* value */
-}
-
-
-Value *Parser::parse_array(void) {
-    size_t len = read_uint();
-    Array *array = new Array(len);
-    for (size_t i = 0; i < len; ++i) {
-        array->values[i] = parse_value();
-    }
-    return array;
-}
-
-
-void Parser::scan_array(void) {
-    size_t len = read_uint();
-    for (size_t i = 0; i < len; ++i) {
-        scan_value();
-    }
-}
-
-
-Value *Parser::parse_blob(void) {
-    size_t size = read_uint();
-    Blob *blob = new Blob(size);
-    if (size) {
-        file->read(blob->buf, (unsigned)size);
-    }
-    return blob;
-}
-
-
-void Parser::scan_blob(void) {
-    size_t size = read_uint();
-    if (size) {
-        file->skip(size);
-    }
-}
-
-
-Value *Parser::parse_struct() {
-    StructSig *sig = parse_struct_sig();
-    Struct *value = new Struct(sig);
-
-    for (size_t i = 0; i < sig->num_members; ++i) {
-        value->members[i] = parse_value();
-    }
-
-    return value;
-}
-
-
-void Parser::scan_struct() {
-    StructSig *sig = parse_struct_sig();
-    for (size_t i = 0; i < sig->num_members; ++i) {
-        scan_value();
-    }
-}
-
-
-Value *Parser::parse_opaque() {
-    unsigned long long addr;
-    addr = read_uint();
-    return new Pointer(addr);
-}
-
-
-void Parser::scan_opaque() {
-    skip_uint();
-}
-
-
-const char * Parser::read_string(void) {
-    size_t len = read_uint();
-    char * value = new char[len + 1];
-    if (len) {
-        file->read(value, (unsigned)len);
-    }
-    value[len] = 0;
-#if TRACE_VERBOSE
-    std::cerr << "\tSTRING \"" << value << "\"\n";
-#endif
-    return value;
-}
-
-
-void Parser::skip_string(void) {
-    size_t len = read_uint();
-    file->skip(len);
-}
-
-
-unsigned long long Parser::read_uint(void) {
-    unsigned long long value = 0;
-    int c;
-    unsigned shift = 0;
-    do {
-        c = file->getc();
-        if (c == -1) {
-            break;
-        }
-        value |= (unsigned long long)(c & 0x7f) << shift;
-        shift += 7;
-    } while(c & 0x80);
-#if TRACE_VERBOSE
-    std::cerr << "\tUINT " << value << "\n";
-#endif
-    return value;
-}
-
-
-void Parser::skip_uint(void) {
-    int c;
-    do {
-        c = file->getc();
-        if (c == -1) {
-            break;
-        }
-    } while(c & 0x80);
-}
-
-
-inline int Parser::read_byte(void) {
-    int c = file->getc();
-#if TRACE_VERBOSE
-    if (c < 0)
-        std::cerr << "\tEOF" << "\n";
-    else
-        std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n";
-#endif
-    return c;
-}
-
-
-inline void Parser::skip_byte(void) {
-    file->skip(1);
-}
-
-
-} /* namespace Trace */
diff --git a/trace_parser.hpp b/trace_parser.hpp
deleted file mode 100644 (file)
index 3aaa6d3..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/**************************************************************************
- *
- * 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 _TRACE_PARSER_HPP_
-#define _TRACE_PARSER_HPP_
-
-
-#include <iostream>
-#include <list>
-
-#include "trace_file.hpp"
-#include "trace_format.hpp"
-#include "trace_model.hpp"
-
-
-namespace Trace {
-
-
-struct ParseBookmark
-{
-    File::Offset offset;
-    unsigned next_call_no;
-};
-
-
-class Parser
-{
-protected:
-    File *file;
-
-    enum Mode {
-        FULL = 0,
-        SCAN,
-        SKIP
-    };
-
-    typedef std::list<Call *> CallList;
-    CallList calls;
-
-    // Helper template that extends a base signature structure, with additional
-    // parsing information.
-    template< class T >
-    struct SigState : public T {
-        // Offset in the file of where signature was defined.  It is used when
-        // reparsing to determine whether the signature definition is to be
-        // expected next or not.
-        File::Offset offset;
-    };
-
-    typedef SigState<FunctionSig> FunctionSigState;
-    typedef SigState<StructSig> StructSigState;
-    typedef SigState<EnumSig> EnumSigState;
-    typedef SigState<BitmaskSig> BitmaskSigState;
-
-    typedef std::vector<FunctionSigState *> FunctionMap;
-    typedef std::vector<StructSigState *> StructMap;
-    typedef std::vector<EnumSigState *> EnumMap;
-    typedef std::vector<BitmaskSigState *> BitmaskMap;
-
-    FunctionMap functions;
-    StructMap structs;
-    EnumMap enums;
-    BitmaskMap bitmasks;
-
-    unsigned next_call_no;
-
-public:
-    unsigned long long version;
-
-    Parser();
-
-    ~Parser();
-
-    bool open(const char *filename);
-
-    void close(void);
-
-    Call *parse_call(void) {
-        return parse_call(FULL);
-    }
-
-    bool supportsOffsets() const
-    {
-        return file->supportsOffsets();
-    }
-
-    void getBookmark(ParseBookmark &bookmark);
-
-    void setBookmark(const ParseBookmark &bookmark);
-
-    int percentRead()
-    {
-        return file->percentRead();
-    }
-
-    Call *scan_call() {
-        return parse_call(SCAN);
-    }
-
-protected:
-    Call *parse_call(Mode mode);
-
-    FunctionSig *parse_function_sig(void);
-    StructSig *parse_struct_sig();
-    EnumSig *parse_enum_sig();
-    BitmaskSig *parse_bitmask_sig();
-    
-    Call *parse_Call(Mode mode);
-
-    void parse_enter(Mode mode);
-
-    Call *parse_leave(Mode mode);
-
-    bool parse_call_details(Call *call, Mode mode);
-
-    void parse_arg(Call *call, Mode mode);
-
-    Value *parse_value(void);
-    void scan_value(void);
-    inline Value *parse_value(Mode mode) {
-        if (mode == FULL) {
-            return parse_value();
-        } else {
-            scan_value();
-            return NULL;
-        }
-    }
-
-    Value *parse_sint();
-    void scan_sint();
-
-    Value *parse_uint();
-    void scan_uint();
-
-    Value *parse_float();
-    void scan_float();
-
-    Value *parse_double();
-    void scan_double();
-
-    Value *parse_string();
-    void scan_string();
-
-    Value *parse_enum();
-    void scan_enum();
-
-    Value *parse_bitmask();
-    void scan_bitmask();
-
-    Value *parse_array(void);
-    void scan_array(void);
-
-    Value *parse_blob(void);
-    void scan_blob(void);
-
-    Value *parse_struct();
-    void scan_struct();
-
-    Value *parse_opaque();
-    void scan_opaque();
-
-    const char * read_string(void);
-    void skip_string(void);
-
-    unsigned long long read_uint(void);
-    void skip_uint(void);
-
-    inline int read_byte(void);
-    inline void skip_byte(void);
-};
-
-
-} /* namespace Trace */
-
-#endif /* _TRACE_PARSER_HPP_ */
diff --git a/trace_snappyfile.cpp b/trace_snappyfile.cpp
deleted file mode 100644 (file)
index 4dbe42d..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Zack Rusin
- * 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.
- *
- **************************************************************************/
-
-
-#include "trace_snappyfile.hpp"
-
-#include <snappy.h>
-
-#include <iostream>
-
-#include <assert.h>
-#include <string.h>
-
-using namespace Trace;
-
-/*
- * Snappy file format.
- * -------------------
- *
- * Snappy at its core is just a compressoin algorithm so we're
- * creating a new file format which uses snappy compression
- * to hold the trace data.
- *
- * The file is composed of a number of chunks, they are:
- * chunk {
- *     uint32 - specifying the length of the compressed data
- *     compressed data, in little endian
- * }
- * File can contain any number of such chunks.
- * The default size of an uncompressed chunk is specified in
- * SNAPPY_CHUNK_SIZE.
- *
- * Note:
- * Currently the default size for a a to-be-compressed data is
- * 1mb, meaning that the compressed data will be <= 1mb.
- * The reason it's 1mb is because it seems
- * to offer a pretty good compression/disk io speed ratio
- * but that might change.
- *
- */
-
-SnappyFile::SnappyFile(const std::string &filename,
-                              File::Mode mode)
-    : File(),
-      m_cache(0),
-      m_cachePtr(0),
-      m_cacheSize(0)
-{
-    size_t maxCompressedLength =
-        snappy::MaxCompressedLength(SNAPPY_CHUNK_SIZE);
-    m_compressedCache = new char[maxCompressedLength];
-}
-
-SnappyFile::~SnappyFile()
-{
-    delete [] m_compressedCache;
-    delete [] m_cache;
-}
-
-bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
-{
-    std::ios_base::openmode fmode = std::fstream::binary;
-    if (mode == File::Write) {
-        fmode |= (std::fstream::out | std::fstream::trunc);
-        createCache(SNAPPY_CHUNK_SIZE);
-    } else if (mode == File::Read) {
-        fmode |= std::fstream::in;
-    }
-
-    m_stream.open(filename.c_str(), fmode);
-
-    //read in the initial buffer if we're reading
-    if (m_stream.is_open() && mode == File::Read) {
-        m_stream.seekg(0, std::ios::end);
-        m_endPos = m_stream.tellg();
-        m_stream.seekg(0, std::ios::beg);
-
-        // read the snappy file identifier
-        unsigned char byte1, byte2;
-        m_stream >> byte1;
-        m_stream >> byte2;
-        assert(byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
-
-        flushReadCache();
-    } else if (m_stream.is_open() && mode == File::Write) {
-        // write the snappy file identifier
-        m_stream << SNAPPY_BYTE1;
-        m_stream << SNAPPY_BYTE2;
-    }
-    return m_stream.is_open();
-}
-
-bool SnappyFile::rawWrite(const void *buffer, size_t length)
-{
-    if (freeCacheSize() > length) {
-        memcpy(m_cachePtr, buffer, length);
-        m_cachePtr += length;
-    } else if (freeCacheSize() == length) {
-        memcpy(m_cachePtr, buffer, length);
-        m_cachePtr += length;
-        flushWriteCache();
-    } else {
-        int sizeToWrite = length;
-
-        while (sizeToWrite >= freeCacheSize()) {
-            int endSize = freeCacheSize();
-            int offset = length - sizeToWrite;
-            memcpy(m_cachePtr, (const char*)buffer + offset, endSize);
-            sizeToWrite -= endSize;
-            m_cachePtr += endSize;
-            flushWriteCache();
-        }
-        if (sizeToWrite) {
-            int offset = length - sizeToWrite;
-            memcpy(m_cachePtr, (const char*)buffer + offset, sizeToWrite);
-            m_cachePtr += sizeToWrite;
-        }
-    }
-
-    return true;
-}
-
-bool SnappyFile::rawRead(void *buffer, size_t length)
-{
-    if (endOfData()) {
-        return false;
-    }
-
-    if (freeCacheSize() >= length) {
-        memcpy(buffer, m_cachePtr, length);
-        m_cachePtr += length;
-    } else {
-        size_t sizeToRead = length;
-        size_t offset = 0;
-        while (sizeToRead) {
-            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
-            offset = length - sizeToRead;
-            memcpy((char*)buffer + offset, m_cachePtr, chunkSize);
-            m_cachePtr += chunkSize;
-            sizeToRead -= chunkSize;
-            if (sizeToRead > 0) {
-                flushReadCache();
-            }
-            if (!m_cacheSize) {
-                break;
-            }
-        }
-    }
-
-    return true;
-}
-
-int SnappyFile::rawGetc()
-{
-    int c = 0;
-    if (!rawRead(&c, 1))
-        return -1;
-    return c;
-}
-
-void SnappyFile::rawClose()
-{
-    if (m_mode == File::Write) {
-        flushWriteCache();
-    }
-    m_stream.close();
-    delete [] m_cache;
-    m_cache = NULL;
-    m_cachePtr = NULL;
-}
-
-void SnappyFile::rawFlush()
-{
-    assert(m_mode == File::Write);
-    flushWriteCache();
-    m_stream.flush();
-}
-
-void SnappyFile::flushWriteCache()
-{
-    size_t inputLength = usedCacheSize();
-
-    if (inputLength) {
-        size_t compressedLength;
-
-        ::snappy::RawCompress(m_cache, inputLength,
-                              m_compressedCache, &compressedLength);
-
-        writeCompressedLength(compressedLength);
-        m_stream.write(m_compressedCache, compressedLength);
-        m_cachePtr = m_cache;
-    }
-    assert(m_cachePtr == m_cache);
-}
-
-void SnappyFile::flushReadCache(size_t skipLength)
-{
-    //assert(m_cachePtr == m_cache + m_cacheSize);
-    m_currentOffset.chunk = m_stream.tellg();
-    size_t compressedLength;
-    compressedLength = readCompressedLength();
-
-    if (compressedLength) {
-        m_stream.read((char*)m_compressedCache, compressedLength);
-        ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
-                                        &m_cacheSize);
-        createCache(m_cacheSize);
-        if (skipLength < m_cacheSize) {
-            ::snappy::RawUncompress(m_compressedCache, compressedLength,
-                                    m_cache);
-        }
-    } else {
-        createCache(0);
-    }
-}
-
-void SnappyFile::createCache(size_t size)
-{
-    // TODO: only re-allocate if the current buffer is not big enough
-
-    if (m_cache) {
-        delete [] m_cache;
-    }
-
-    if (size) {
-        m_cache = new char[size];
-    } else {
-        m_cache = NULL;
-    }
-
-    m_cachePtr = m_cache;
-    m_cacheSize = size;
-}
-
-void SnappyFile::writeCompressedLength(size_t length)
-{
-    unsigned char buf[4];
-    buf[0] = length & 0xff; length >>= 8;
-    buf[1] = length & 0xff; length >>= 8;
-    buf[2] = length & 0xff; length >>= 8;
-    buf[3] = length & 0xff; length >>= 8;
-    assert(length == 0);
-    m_stream.write((const char *)buf, sizeof buf);
-}
-
-size_t SnappyFile::readCompressedLength()
-{
-    unsigned char buf[4];
-    size_t length;
-    m_stream.read((char *)buf, sizeof buf);
-    if (m_stream.fail()) {
-        length = 0;
-    } else {
-        length  =  (size_t)buf[0];
-        length |= ((size_t)buf[1] <<  8);
-        length |= ((size_t)buf[2] << 16);
-        length |= ((size_t)buf[3] << 24);
-    }
-    return length;
-}
-
-bool SnappyFile::supportsOffsets() const
-{
-    return true;
-}
-
-File::Offset SnappyFile::currentOffset()
-{
-    m_currentOffset.offsetInChunk = m_cachePtr - m_cache;
-    return m_currentOffset;
-}
-
-void SnappyFile::setCurrentOffset(const File::Offset &offset)
-{
-    // to remove eof bit
-    m_stream.clear();
-    // seek to the start of a chunk
-    m_stream.seekg(offset.chunk, std::ios::beg);
-    // load the chunk
-    flushReadCache();
-    assert(m_cacheSize >= offset.offsetInChunk);
-    // seek within our cache to the correct location within the chunk
-    m_cachePtr = m_cache + offset.offsetInChunk;
-
-}
-
-bool SnappyFile::rawSkip(size_t length)
-{
-    if (endOfData()) {
-        return false;
-    }
-
-    if (freeCacheSize() >= length) {
-        m_cachePtr += length;
-    } else {
-        size_t sizeToRead = length;
-        while (sizeToRead) {
-            size_t chunkSize = std::min(freeCacheSize(), sizeToRead);
-            m_cachePtr += chunkSize;
-            sizeToRead -= chunkSize;
-            if (sizeToRead > 0) {
-                flushReadCache(sizeToRead);
-            }
-            if (!m_cacheSize) {
-                break;
-            }
-        }
-    }
-
-    return true;
-}
-
-int SnappyFile::rawPercentRead()
-{
-    return 100 * (double(m_stream.tellg()) / double(m_endPos));
-}
diff --git a/trace_snappyfile.hpp b/trace_snappyfile.hpp
deleted file mode 100644 (file)
index 33159ec..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2011 Zack Rusin
- * 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 TRACE_SNAPPYFILE_HPP
-#define TRACE_SNAPPYFILE_HPP
-
-#include <assert.h>
-
-#include "trace_file.hpp"
-
-#include <string>
-#include <fstream>
-
-namespace snappy {
-    class File;
-}
-
-namespace Trace {
-
-#define SNAPPY_CHUNK_SIZE (1 * 1024 * 1024)
-
-#define SNAPPY_BYTE1 'a'
-#define SNAPPY_BYTE2 't'
-
-
-class SnappyFile : public File {
-public:
-    SnappyFile(const std::string &filename = std::string(),
-               File::Mode mode = File::Read);
-    virtual ~SnappyFile();
-
-    virtual bool supportsOffsets() const;
-    virtual File::Offset currentOffset();
-    virtual void setCurrentOffset(const File::Offset &offset);
-protected:
-    virtual bool rawOpen(const std::string &filename, File::Mode mode);
-    virtual bool rawWrite(const void *buffer, size_t length);
-    virtual bool rawRead(void *buffer, size_t length);
-    virtual int rawGetc();
-    virtual void rawClose();
-    virtual void rawFlush();
-    virtual bool rawSkip(size_t length);
-    virtual int rawPercentRead();
-
-private:
-    inline size_t usedCacheSize() const
-    {
-        assert(m_cachePtr >= m_cache);
-        return m_cachePtr - m_cache;
-    }
-    inline size_t freeCacheSize() const
-    {
-        assert(m_cacheSize >= usedCacheSize());
-        if (m_cacheSize > 0) {
-            return m_cacheSize - usedCacheSize();
-        } else {
-            return 0;
-        }
-    }
-    inline bool endOfData() const
-    {
-        return m_stream.eof() && freeCacheSize() == 0;
-    }
-    void flushWriteCache();
-    void flushReadCache(size_t skipLength = 0);
-    void createCache(size_t size);
-    void writeCompressedLength(size_t length);
-    size_t readCompressedLength();
-private:
-    std::fstream m_stream;
-    char *m_cache;
-    char *m_cachePtr;
-    size_t m_cacheSize;
-
-    char *m_compressedCache;
-
-    File::Offset m_currentOffset;
-    std::streampos m_endPos;
-};
-
-}
-
-#endif // TRACE_SNAPPYFILE_HPP
diff --git a/trace_writer.cpp b/trace_writer.cpp
deleted file mode 100644 (file)
index 5a5f1f7..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2007-2009 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.
- *
- **************************************************************************/
-
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "os.hpp"
-#include "trace_writer.hpp"
-#include "trace_snappyfile.hpp"
-#include "trace_format.hpp"
-
-
-namespace Trace {
-
-
-Writer::Writer() :
-    call_no(0)
-{
-    m_file = new Trace::SnappyFile;
-    close();
-}
-
-Writer::~Writer()
-{
-    close();
-    delete m_file;
-    m_file = NULL;
-}
-
-void
-Writer::close(void) {
-    m_file->close();
-}
-
-bool
-Writer::open(const char *filename) {
-    close();
-
-    if (!m_file->open(filename, File::Write)) {
-        return false;
-    }
-
-    call_no = 0;
-    functions.clear();
-    structs.clear();
-    enums.clear();
-    bitmasks.clear();
-
-    _writeUInt(TRACE_VERSION);
-
-    return true;
-}
-
-void inline
-Writer::_write(const void *sBuffer, size_t dwBytesToWrite) {
-    m_file->write(sBuffer, dwBytesToWrite);
-}
-
-void inline
-Writer::_writeByte(char c) {
-    _write(&c, 1);
-}
-
-void inline
-Writer::_writeUInt(unsigned long long value) {
-    char buf[2 * sizeof value];
-    unsigned len;
-
-    len = 0;
-    do {
-        assert(len < sizeof buf);
-        buf[len] = 0x80 | (value & 0x7f);
-        value >>= 7;
-        ++len;
-    } while (value);
-
-    assert(len);
-    buf[len - 1] &= 0x7f;
-
-    _write(buf, len);
-}
-
-void inline
-Writer::_writeFloat(float value) {
-    assert(sizeof value == 4);
-    _write((const char *)&value, sizeof value);
-}
-
-void inline
-Writer::_writeDouble(double value) {
-    assert(sizeof value == 8);
-    _write((const char *)&value, sizeof value);
-}
-
-void inline
-Writer::_writeString(const char *str) {
-    size_t len = strlen(str);
-    _writeUInt(len);
-    _write(str, len);
-}
-
-inline bool lookup(std::vector<bool> &map, size_t index) {
-    if (index >= map.size()) {
-        map.resize(index + 1);
-        return false;
-    } else {
-        return map[index];
-    }
-}
-
-unsigned Writer::beginEnter(const FunctionSig *sig) {
-    _writeByte(Trace::EVENT_ENTER);
-    _writeUInt(sig->id);
-    if (!lookup(functions, sig->id)) {
-        _writeString(sig->name);
-        _writeUInt(sig->num_args);
-        for (unsigned i = 0; i < sig->num_args; ++i) {
-            _writeString(sig->arg_names[i]);
-        }
-        functions[sig->id] = true;
-    }
-
-    return call_no++;
-}
-
-void Writer::endEnter(void) {
-    _writeByte(Trace::CALL_END);
-}
-
-void Writer::beginLeave(unsigned call) {
-    _writeByte(Trace::EVENT_LEAVE);
-    _writeUInt(call);
-}
-
-void Writer::endLeave(void) {
-    _writeByte(Trace::CALL_END);
-}
-
-void Writer::beginArg(unsigned index) {
-    _writeByte(Trace::CALL_ARG);
-    _writeUInt(index);
-}
-
-void Writer::beginReturn(void) {
-    _writeByte(Trace::CALL_RET);
-}
-
-void Writer::beginArray(size_t length) {
-    _writeByte(Trace::TYPE_ARRAY);
-    _writeUInt(length);
-}
-
-void Writer::beginStruct(const StructSig *sig) {
-    _writeByte(Trace::TYPE_STRUCT);
-    _writeUInt(sig->id);
-    if (!lookup(structs, sig->id)) {
-        _writeString(sig->name);
-        _writeUInt(sig->num_members);
-        for (unsigned i = 0; i < sig->num_members; ++i) {
-            _writeString(sig->member_names[i]);
-        }
-        structs[sig->id] = true;
-    }
-}
-
-void Writer::writeBool(bool value) {
-    _writeByte(value ? Trace::TYPE_TRUE : Trace::TYPE_FALSE);
-}
-
-void Writer::writeSInt(signed long long value) {
-    if (value < 0) {
-        _writeByte(Trace::TYPE_SINT);
-        _writeUInt(-value);
-    } else {
-        _writeByte(Trace::TYPE_UINT);
-        _writeUInt(value);
-    }
-}
-
-void Writer::writeUInt(unsigned long long value) {
-    _writeByte(Trace::TYPE_UINT);
-    _writeUInt(value);
-}
-
-void Writer::writeFloat(float value) {
-    _writeByte(Trace::TYPE_FLOAT);
-    _writeFloat(value);
-}
-
-void Writer::writeDouble(double value) {
-    _writeByte(Trace::TYPE_DOUBLE);
-    _writeDouble(value);
-}
-
-void Writer::writeString(const char *str) {
-    if (!str) {
-        Writer::writeNull();
-        return;
-    }
-    _writeByte(Trace::TYPE_STRING);
-    _writeString(str);
-}
-
-void Writer::writeString(const char *str, size_t len) {
-    if (!str) {
-        Writer::writeNull();
-        return;
-    }
-    _writeByte(Trace::TYPE_STRING);
-    _writeUInt(len);
-    _write(str, len);
-}
-
-void Writer::writeWString(const wchar_t *str) {
-    if (!str) {
-        Writer::writeNull();
-        return;
-    }
-    _writeByte(Trace::TYPE_STRING);
-    _writeString("<wide-string>");
-}
-
-void Writer::writeBlob(const void *data, size_t size) {
-    if (!data) {
-        Writer::writeNull();
-        return;
-    }
-    _writeByte(Trace::TYPE_BLOB);
-    _writeUInt(size);
-    if (size) {
-        _write(data, size);
-    }
-}
-
-void Writer::writeEnum(const EnumSig *sig) {
-    _writeByte(Trace::TYPE_ENUM);
-    _writeUInt(sig->id);
-    if (!lookup(enums, sig->id)) {
-        _writeString(sig->name);
-        Writer::writeSInt(sig->value);
-        enums[sig->id] = true;
-    }
-}
-
-void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
-    _writeByte(Trace::TYPE_BITMASK);
-    _writeUInt(sig->id);
-    if (!lookup(bitmasks, sig->id)) {
-        _writeUInt(sig->num_flags);
-        for (unsigned i = 0; i < sig->num_flags; ++i) {
-            if (i != 0 && sig->flags[i].value == 0) {
-                OS::DebugMessage("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name);
-            }
-            _writeString(sig->flags[i].name);
-            _writeUInt(sig->flags[i].value);
-        }
-        bitmasks[sig->id] = true;
-    }
-    _writeUInt(value);
-}
-
-void Writer::writeNull(void) {
-    _writeByte(Trace::TYPE_NULL);
-}
-
-void Writer::writeOpaque(const void *addr) {
-    if (!addr) {
-        Writer::writeNull();
-        return;
-    }
-    _writeByte(Trace::TYPE_OPAQUE);
-    _writeUInt((size_t)addr);
-}
-
-
-} /* namespace Trace */
-
diff --git a/trace_writer.hpp b/trace_writer.hpp
deleted file mode 100644 (file)
index dfb76b2..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2007-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.
- *
- **************************************************************************/
-
-/*
- * Trace writing functions.
- */
-
-#ifndef _TRACE_WRITER_HPP_
-#define _TRACE_WRITER_HPP_
-
-
-#include <stddef.h>
-
-#include <vector>
-
-#include "trace_model.hpp"
-
-
-namespace Trace {
-    class File;
-
-    class Writer {
-    protected:
-        File *m_file;
-        unsigned call_no;
-
-        std::vector<bool> functions;
-        std::vector<bool> structs;
-        std::vector<bool> enums;
-        std::vector<bool> bitmasks;
-
-    public:
-        Writer();
-        ~Writer();
-
-        bool open(const char *filename);
-        void close(void);
-
-        unsigned beginEnter(const FunctionSig *sig);
-        void endEnter(void);
-
-        void beginLeave(unsigned call);
-        void endLeave(void);
-
-        void beginArg(unsigned index);
-        inline void endArg(void) {}
-
-        void beginReturn(void);
-        inline void endReturn(void) {}
-
-        void beginArray(size_t length);
-        inline void endArray(void) {}
-
-        inline void beginElement(void) {}
-        inline void endElement(void) {}
-
-        void beginStruct(const StructSig *sig);
-        inline void endStruct(void) {}
-
-        void writeBool(bool value);
-        void writeSInt(signed long long value);
-        void writeUInt(unsigned long long value);
-        void writeFloat(float value);
-        void writeDouble(double value);
-        void writeString(const char *str);
-        void writeString(const char *str, size_t size);
-        void writeWString(const wchar_t *str);
-        void writeBlob(const void *data, size_t size);
-        void writeEnum(const EnumSig *sig);
-        void writeBitmask(const BitmaskSig *sig, unsigned long long value);
-        void writeNull(void);
-        void writeOpaque(const void *ptr);
-
-        void writeCall(Call *call);
-
-    protected:
-        void inline _write(const void *sBuffer, size_t dwBytesToWrite);
-        void inline _writeByte(char c);
-        void inline _writeUInt(unsigned long long value);
-        void inline _writeFloat(float value);
-        void inline _writeDouble(double value);
-        void inline _writeString(const char *str);
-
-    };
-
-    /**
-     * A specialized Writer class, mean to trace the current process.
-     *
-     * In particular:
-     * - it creates a trace file based on the current process name
-     * - uses mutexes to allow tracing from multiple threades
-     * - flushes the output to ensure the last call is traced in event of
-     *   abnormal termination
-     */
-    class LocalWriter : public Writer {
-    protected:
-        int acquired;
-
-    public:
-        /**
-         * Should never called directly -- use localWriter singleton below instead.
-         */
-        LocalWriter();
-        ~LocalWriter();
-
-        void open(void);
-
-        unsigned beginEnter(const FunctionSig *sig);
-        void endEnter(void);
-
-        void beginLeave(unsigned call);
-        void endLeave(void);
-
-        void flush(void);
-    };
-
-    /**
-     * Singleton.
-     */
-    extern LocalWriter localWriter;
-}
-
-#endif /* _TRACE_WRITER_HPP_ */