<commit_before>// This file is part of the uSTL library, an STL implementation.
//
// Copyright (c) 2005 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the MIT License.

#include "uexception.h"
#include "ustring.h"
#include "mistream.h"
#include "sostream.h"
#include "strmsize.h"
#include "uspecial.h"
#include <errno.h>

#if HAVE_CXXABI_H && WANT_NAME_DEMANGLING
extern "C" char* __cxa_demangle (const char* mangled_name, char* output_buffer, size_t* length, int* status);
#endif

namespace ustl {

//----------------------------------------------------------------------

/// \brief Returns a descriptive error message. fmt="%s"
/// Overloads of this functions must set NULL as the default fmt
/// argument and handle that case to provide a default format string
/// in case the user does not have a localized one. The format
/// string should be shown in the documentation to not require
/// translators to look through code. Also, this function must
/// not throw anything, so you must wrap memory allocation routines
/// (like string::format, for instance) in a try{}catch(...){} block.
///
void exception::info (string& msgbuf, const char*) const throw()
{
    USTL_TRY { msgbuf.format ("%s", what()); } USTL_CATCH_ALL;
}

/// Reads the exception from stream \p is.
void exception::read (istream& is)
{
    uint32_t stmSize;
    xfmt_t fmt = xfmt_Exception;
    is >> fmt >> stmSize >> m_Backtrace;
    assert (fmt == m_Format && "The saved exception is of a different type.");
    assert ((stmSize + 8) - exception::stream_size() <= is.remaining() && "The saved exception data is corrupt.");
    m_Format = fmt;
}

/// Writes the exception into stream \p os as an IFF chunk.
void exception::write (ostream& os) const
{
    os << m_Format << uint32_t(stream_size() - 8) << m_Backtrace;
}

/// Writes the exception as text into stream \p os.
void exception::text_write (ostringstream& os) const
{
    USTL_TRY {
	string buf;
	info (buf);
	os << buf;
    } USTL_CATCH_ALL
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p nBytes is the size of the attempted allocation.
bad_alloc::bad_alloc (size_t nBytes) throw()
: ustl::exception(),
  m_nBytesRequested (nBytes)
{
    set_format (xfmt_BadAlloc);
}

/// Returns a descriptive error message. fmt="failed to allocate %d bytes"
void bad_alloc::info (string& msgbuf, const char* fmt) const throw()
{
    if (!fmt) fmt = "failed to allocate %d bytes";
    USTL_TRY { msgbuf.format (fmt, m_nBytesRequested); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void bad_alloc::read (istream& is)
{
    ustl::exception::read (is);
    is >> m_nBytesRequested;
}

/// Writes the exception into stream \p os.
void bad_alloc::write (ostream& os) const
{
    ustl::exception::write (os);
    os << m_nBytesRequested;
}

/// Returns the size of the written exception.
size_t bad_alloc::stream_size (void) const
{
    return (ustl::exception::stream_size() + stream_size_of(m_nBytesRequested));
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p operation is the function that returned the error code.
libc_exception::libc_exception (const char* operation) throw()
: exception(),
  m_Errno (errno),
  m_Operation (operation)
{
    set_format (xfmt_LibcException);
}

/// Copies object \p v.
libc_exception::libc_exception (const libc_exception& v) throw()
: exception (v),
  m_Errno (v.m_Errno),
  m_Operation (v.m_Operation)
{
}

/// Copies object \p v.
const libc_exception& libc_exception::operator= (const libc_exception& v)
{
    m_Errno = v.m_Errno;
    m_Operation = v.m_Operation;
    return (*this);
}

/// Returns a descriptive error message. fmt="%s: %m"
void libc_exception::info (string& msgbuf, const char* fmt) const throw()
{
    if (!fmt) fmt = "%s: %m";
    USTL_TRY { msgbuf.format (fmt, m_Operation, m_Errno, m_Errno); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void libc_exception::read (istream& is)
{
    exception::read (is);
    is >> m_Errno >> m_Operation;
}

/// Writes the exception into stream \p os.
void libc_exception::write (ostream& os) const
{
    exception::write (os);
    os << m_Errno << m_Operation;
}

/// Returns the size of the written exception.
size_t libc_exception::stream_size (void) const
{
    return (exception::stream_size() +
	    stream_size_of(m_Errno) +
	    stream_size_of(m_Operation));
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p operation is the function that returned the error code.
file_exception::file_exception (const char* operation, const char* filename) throw()
: libc_exception (operation)
{
    memset (m_Filename, 0, VectorSize(m_Filename));
    set_format (xfmt_FileException);
    if (filename) {
	strncpy (m_Filename, filename, VectorSize(m_Filename));
	m_Filename [VectorSize(m_Filename) - 1] = 0;
    }
}

/// Returns a descriptive error message. fmt="%s %s: %m"
void file_exception::info (string& msgbuf, const char* fmt) const throw()
{
    if (!fmt) fmt = "%s %s: %m";
    USTL_TRY { msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, m_Errno); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void file_exception::read (istream& is)
{
    libc_exception::read (is);
    string filename;
    is >> filename;
    is.align (8);
    filename.copyto (filename, VectorSize(m_Filename));
}

/// Writes the exception into stream \p os.
void file_exception::write (ostream& os) const
{
    libc_exception::write (os);
    os << string (m_Filename);
    os.align (8);
}

/// Returns the size of the written exception.
size_t file_exception::stream_size (void) const
{
    return (libc_exception::stream_size() +
	    Align (stream_size_of (string (m_Filename)), 8));
}

//----------------------------------------------------------------------

/// \brief Uses C++ ABI call, if available to demangle the contents of \p buf.
///
/// The result is written to \p buf, with the maximum size of \p bufSize, and
/// is zero-terminated. The return value is \p buf.
///
const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize)
{
    size_t bl = strlen (buf);
#if HAVE_CXXABI_H && WANT_NAME_DEMANGLING
    char dmname [256];
    size_t sz = VectorSize(dmname);
    int bFailed;
    __cxa_demangle (buf, dmname, &sz, &bFailed);
    if (!bFailed) {
	bl = min (strlen (dmname), bufSize - 1);
	memcpy (buf, dmname, bl);
	buf[bl] = 0;
    }
#else
    bl = min (bl, bufSize);
#endif
    if (pdmSize)
	*pdmSize = bl;
    return (buf);
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p operation is the function that returned the error code.
stream_bounds_exception::stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw()
: libc_exception (operation),
  m_TypeName (type),
  m_Offset (offset),
  m_Expected (expected),
  m_Remaining (remaining)
{
    set_format (xfmt_StreamBoundsException);
}

/// Returns a descriptive error message. fmt="%s stream %s: @%u: expected %u, available %u";
void stream_bounds_exception::info (string& msgbuf, const char* fmt) const throw()
{
    char typeName [256];
    strncpy (typeName, m_TypeName, VectorSize(typeName));
    typeName[VectorSize(typeName)-1] = 0;
    if (!fmt) fmt = "%s stream %s: @0x%X: need %u bytes, have %u";
    USTL_TRY { msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void stream_bounds_exception::read (istream& is)
{
    libc_exception::read (is);
    is >> m_TypeName >> m_Offset >> m_Expected >> m_Remaining;
}

/// Writes the exception into stream \p os.
void stream_bounds_exception::write (ostream& os) const
{
    libc_exception::write (os);
    os << m_TypeName << m_Offset << m_Expected << m_Remaining;
}

/// Returns the size of the written exception.
size_t stream_bounds_exception::stream_size (void) const
{
    return (libc_exception::stream_size() +
	    stream_size_of(m_TypeName) +
	    stream_size_of(m_Offset) +
	    stream_size_of(m_Expected) +
	    stream_size_of(m_Remaining));
}

} // namespace ustl
<commit_msg>Replace %m with manual strerror() call.<commit_after>// This file is part of the uSTL library, an STL implementation.
//
// Copyright (c) 2005 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the MIT License.

#include "uexception.h"
#include "ustring.h"
#include "mistream.h"
#include "sostream.h"
#include "strmsize.h"
#include "uspecial.h"
#include <errno.h>

#if HAVE_CXXABI_H && WANT_NAME_DEMANGLING
extern "C" char* __cxa_demangle (const char* mangled_name, char* output_buffer, size_t* length, int* status);
#endif

namespace ustl {

//----------------------------------------------------------------------

/// \brief Returns a descriptive error message. fmt="%s"
/// Overloads of this functions must set NULL as the default fmt
/// argument and handle that case to provide a default format string
/// in case the user does not have a localized one. The format
/// string should be shown in the documentation to not require
/// translators to look through code. Also, this function must
/// not throw anything, so you must wrap memory allocation routines
/// (like string::format, for instance) in a try{}catch(...){} block.
///
void exception::info (string& msgbuf, const char*) const throw()
{
    USTL_TRY { msgbuf.format ("%s", what()); } USTL_CATCH_ALL;
}

/// Reads the exception from stream \p is.
void exception::read (istream& is)
{
    uint32_t stmSize = 0;
    xfmt_t fmt = xfmt_Exception;
    is >> fmt >> stmSize >> m_Backtrace;
    assert (fmt == m_Format && "The saved exception is of a different type.");
    assert ((stmSize + 8) - exception::stream_size() <= is.remaining() && "The saved exception data is corrupt.");
    m_Format = fmt;
}

/// Writes the exception into stream \p os as an IFF chunk.
void exception::write (ostream& os) const
{
    os << m_Format << uint32_t(stream_size() - 8) << m_Backtrace;
}

/// Writes the exception as text into stream \p os.
void exception::text_write (ostringstream& os) const
{
    USTL_TRY {
	string buf;
	info (buf);
	os << buf;
    } USTL_CATCH_ALL
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p nBytes is the size of the attempted allocation.
bad_alloc::bad_alloc (size_t nBytes) throw()
: ustl::exception(),
  m_nBytesRequested (nBytes)
{
    set_format (xfmt_BadAlloc);
}

/// Returns a descriptive error message. fmt="failed to allocate %d bytes"
void bad_alloc::info (string& msgbuf, const char* fmt) const throw()
{
    if (!fmt) fmt = "failed to allocate %d bytes";
    USTL_TRY { msgbuf.format (fmt, m_nBytesRequested); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void bad_alloc::read (istream& is)
{
    ustl::exception::read (is);
    is >> m_nBytesRequested;
}

/// Writes the exception into stream \p os.
void bad_alloc::write (ostream& os) const
{
    ustl::exception::write (os);
    os << m_nBytesRequested;
}

/// Returns the size of the written exception.
size_t bad_alloc::stream_size (void) const
{
    return (ustl::exception::stream_size() + stream_size_of(m_nBytesRequested));
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p operation is the function that returned the error code.
libc_exception::libc_exception (const char* operation) throw()
: exception(),
  m_Errno (errno),
  m_Operation (operation)
{
    set_format (xfmt_LibcException);
}

/// Copies object \p v.
libc_exception::libc_exception (const libc_exception& v) throw()
: exception (v),
  m_Errno (v.m_Errno),
  m_Operation (v.m_Operation)
{
}

/// Copies object \p v.
const libc_exception& libc_exception::operator= (const libc_exception& v)
{
    m_Errno = v.m_Errno;
    m_Operation = v.m_Operation;
    return (*this);
}

/// Returns a descriptive error message. fmt="%s: %m"
void libc_exception::info (string& msgbuf, const char* fmt) const throw()
{
    if (!fmt) fmt = "%s: %d %s";
    USTL_TRY { msgbuf.format (fmt, m_Operation, m_Errno, strerror(m_Errno)); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void libc_exception::read (istream& is)
{
    exception::read (is);
    is >> m_Errno >> m_Operation;
}

/// Writes the exception into stream \p os.
void libc_exception::write (ostream& os) const
{
    exception::write (os);
    os << m_Errno << m_Operation;
}

/// Returns the size of the written exception.
size_t libc_exception::stream_size (void) const
{
    return (exception::stream_size() +
	    stream_size_of(m_Errno) +
	    stream_size_of(m_Operation));
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p operation is the function that returned the error code.
file_exception::file_exception (const char* operation, const char* filename) throw()
: libc_exception (operation)
{
    memset (m_Filename, 0, VectorSize(m_Filename));
    set_format (xfmt_FileException);
    if (filename) {
	strncpy (m_Filename, filename, VectorSize(m_Filename));
	m_Filename [VectorSize(m_Filename) - 1] = 0;
    }
}

/// Returns a descriptive error message. fmt="%s %s: %m"
void file_exception::info (string& msgbuf, const char* fmt) const throw()
{
    if (!fmt) fmt = "%s %s: %d %s";
    USTL_TRY { msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, strerror(m_Errno)); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void file_exception::read (istream& is)
{
    libc_exception::read (is);
    string filename;
    is >> filename;
    is.align (8);
    filename.copyto (filename, VectorSize(m_Filename));
}

/// Writes the exception into stream \p os.
void file_exception::write (ostream& os) const
{
    libc_exception::write (os);
    os << string (m_Filename);
    os.align (8);
}

/// Returns the size of the written exception.
size_t file_exception::stream_size (void) const
{
    return (libc_exception::stream_size() +
	    Align (stream_size_of (string (m_Filename)), 8));
}

//----------------------------------------------------------------------

/// \brief Uses C++ ABI call, if available to demangle the contents of \p buf.
///
/// The result is written to \p buf, with the maximum size of \p bufSize, and
/// is zero-terminated. The return value is \p buf.
///
const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize)
{
    size_t bl = strlen (buf);
#if HAVE_CXXABI_H && WANT_NAME_DEMANGLING
    char dmname [256];
    size_t sz = VectorSize(dmname);
    int bFailed;
    __cxa_demangle (buf, dmname, &sz, &bFailed);
    if (!bFailed) {
	bl = min (strlen (dmname), bufSize - 1);
	memcpy (buf, dmname, bl);
	buf[bl] = 0;
    }
#else
    bl = min (bl, bufSize);
#endif
    if (pdmSize)
	*pdmSize = bl;
    return (buf);
}

//----------------------------------------------------------------------

/// Initializes the empty object. \p operation is the function that returned the error code.
stream_bounds_exception::stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw()
: libc_exception (operation),
  m_TypeName (type),
  m_Offset (offset),
  m_Expected (expected),
  m_Remaining (remaining)
{
    set_format (xfmt_StreamBoundsException);
}

/// Returns a descriptive error message. fmt="%s stream %s: @%u: expected %u, available %u";
void stream_bounds_exception::info (string& msgbuf, const char* fmt) const throw()
{
    char typeName [256];
    strncpy (typeName, m_TypeName, VectorSize(typeName));
    typeName[VectorSize(typeName)-1] = 0;
    if (!fmt) fmt = "%s stream %s: @0x%X: need %u bytes, have %u";
    USTL_TRY { msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining); } USTL_CATCH_ALL
}

/// Reads the exception from stream \p is.
void stream_bounds_exception::read (istream& is)
{
    libc_exception::read (is);
    is >> m_TypeName >> m_Offset >> m_Expected >> m_Remaining;
}

/// Writes the exception into stream \p os.
void stream_bounds_exception::write (ostream& os) const
{
    libc_exception::write (os);
    os << m_TypeName << m_Offset << m_Expected << m_Remaining;
}

/// Returns the size of the written exception.
size_t stream_bounds_exception::stream_size (void) const
{
    return (libc_exception::stream_size() +
	    stream_size_of(m_TypeName) +
	    stream_size_of(m_Offset) +
	    stream_size_of(m_Expected) +
	    stream_size_of(m_Remaining));
}

} // namespace ustl
<|endoftext|>


<commit_before>#include <initrd/builder.hpp>

namespace initrd
{
  builder_t::builder_t() {}

  builder_t& builder_t::addFile(file_t file) {

  }

  builder_t& builder_t::addFiles(std::list<file_t> files) {

  }

  const image_t builder_t::build() {

  }
};<commit_msg>Add comments<commit_after>#include <builder.hpp>

namespace initrd
{
  /**
   * \constructor
   */
  builder_t::builder_t() {}

  /**
   * \brief Adds a new file to the image under
   * construction.
   */
  builder_t& builder_t::addFile(file_t file) {

  }

  /**
   * \brief Adds a list of files to the image
   * under construction.
   */
  builder_t& builder_t::addFiles(std::list<file_t> files) {

  }

  /**
   * \return a new image instance built using the
   * previously given file instances.
   */
  const image_t builder_t::build() {

  }
};
<|endoftext|>


<commit_before>class BlockZoomData
{
public:
private:
    int _position;
    int _width;
};

class BlockSizeZoomData
{
    Array<BlockZoomData> _blocks;
};

class ZoomData
{
public:
private:
    Array<BlockSizeZoomData> _levels;
};

class BlockZoom
{
public:
private:
    int _position;
    int _width;
    BlockZoom* _left;
    BlockZoom* _right;
};

class BlockZoomX
{
public:
private:
    FunctionPointer _drawFunc;
    BlockZoom* _left;
    BlockZoom* _right;
};
<commit_msg>More Mandel quadtree<commit_after>class BlockZoomData
{
public:
private:
    int _position;
    int _width;
};

class BlockSizeZoomData
{
    Array<BlockZoomData> _blocks;
};

class ZoomData
{
public:
private:
    Array<BlockSizeZoomData> _levels;
};

class BlockZoom
{
public:
private:
    int _position;
    int _width;
    BlockZoom* _left;
    BlockZoom* _right;
};

class BlockZoomX
{
public:
private:
    FunctionPointer _drawFunc;
    BlockZoom* _left;
    BlockZoom* _right;
};

class BlockZoomY
{
public:
private:
    int _end;
    BlockZoom* _left;
    BlockZoom* _right;
};
<|endoftext|>


<commit_before>#include "gm.h"
#include "SkPicture.h"
#include "SkRectShape.h"
#include "SkBlurDrawLooper.h"

namespace skiagm {

///////////////////////////////////////////////////////////////////////////////

class ShadowsGM : public GM {

public:
    SkPath fCirclePath;
    SkPaint fPaint;
    SkRectShape fRectShape;
    ShadowsGM() {
        fCirclePath.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(10) );
    fPaint.setStrokeWidth(SkIntToScalar(4));
    fPaint.setAntiAlias(true);
    fPaint.setColor(0xFF00FF00);
    fPaint.setStyle(SkPaint::kStroke_Style);
    SkRect rect;
    rect.set(SkIntToScalar(10), SkIntToScalar(10),
             SkIntToScalar(30), SkIntToScalar(30));
    fRectShape.setRect(rect);
    fRectShape.paint().setColor(SK_ColorRED);
    }

    virtual ~ShadowsGM() {
    }

protected:
    virtual SkString onShortName() {
        return SkString("shadows");
    }

    virtual SkISize onISize() {
        return make_isize(200, 80);
    }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

    SkBlurDrawLooper* shadowLoopers[5];
    shadowLoopers[0] =
        new SkBlurDrawLooper (SkIntToScalar(10), SkIntToScalar(5),
                              SkIntToScalar(10), 0xFF0000FF,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag );
    SkAutoUnref aurL0(shadowLoopers[0]);
    shadowLoopers[1] =
        new SkBlurDrawLooper (SkIntToScalar(10), SkIntToScalar(5),
                              SkIntToScalar(10), 0xFF0000FF,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag );
    SkAutoUnref aurL1(shadowLoopers[1]);
    shadowLoopers[2] =
        new SkBlurDrawLooper (SkIntToScalar(5), SkIntToScalar(5),
                              SkIntToScalar(10), 0xFF000000,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag  );
    SkAutoUnref aurL2(shadowLoopers[2]);
    shadowLoopers[3] =
        new SkBlurDrawLooper (SkIntToScalar(5), SkIntToScalar(-5),
                              SkIntToScalar(-10), 0x7FFF0000,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag  );
    SkAutoUnref aurL3(shadowLoopers[3]);
    shadowLoopers[4] =
        new SkBlurDrawLooper (SkIntToScalar(0), SkIntToScalar(5),
                              SkIntToScalar(5), 0xFF000000,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag  );
    SkAutoUnref aurL4(shadowLoopers[4]);

    for (int looper = 0; looper < 5; looper ++)
    {
        fRectShape.paint().setLooper(shadowLoopers[looper]);
        canvas->resetMatrix();
        canvas->translate(SkIntToScalar(looper*40), SkIntToScalar(0));
        canvas->drawShape(&fRectShape);
        fPaint.setLooper(shadowLoopers[looper]);
        canvas->translate(SkIntToScalar(0), SkIntToScalar(40));
        canvas->drawPath(fCirclePath, fPaint);
    }
}

private:
    typedef GM INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

static GM* MyFactory(void*) { return new ShadowsGM; }
static GMRegistry reg(MyFactory);

}
<commit_msg>retool without shapes, which are broken/experimental<commit_after>#include "gm.h"
#include "SkBlurDrawLooper.h"

namespace skiagm {

///////////////////////////////////////////////////////////////////////////////

static void setup(SkPaint* paint, SkColor c, SkScalar strokeWidth) {
    paint->setColor(c);
    if (strokeWidth < 0) {
        paint->setStyle(SkPaint::kFill_Style);
    } else {
        paint->setStyle(SkPaint::kStroke_Style);
        paint->setStrokeWidth(strokeWidth);
    }
}

class ShadowsGM : public GM {
public:
    SkPath fCirclePath;
    SkRect fRect;

    ShadowsGM() {
        fCirclePath.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(10) );
        fRect.set(SkIntToScalar(10), SkIntToScalar(10),
                  SkIntToScalar(30), SkIntToScalar(30));
    }

protected:
    virtual SkString onShortName() {
        return SkString("shadows");
    }

    virtual SkISize onISize() {
        return make_isize(200, 80);
    }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

    SkBlurDrawLooper* shadowLoopers[5];
    shadowLoopers[0] =
        new SkBlurDrawLooper (SkIntToScalar(10), SkIntToScalar(5),
                              SkIntToScalar(10), 0xFF0000FF,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag );
    SkAutoUnref aurL0(shadowLoopers[0]);
    shadowLoopers[1] =
        new SkBlurDrawLooper (SkIntToScalar(10), SkIntToScalar(5),
                              SkIntToScalar(10), 0xFF0000FF,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag );
    SkAutoUnref aurL1(shadowLoopers[1]);
    shadowLoopers[2] =
        new SkBlurDrawLooper (SkIntToScalar(5), SkIntToScalar(5),
                              SkIntToScalar(10), 0xFF000000,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag  );
    SkAutoUnref aurL2(shadowLoopers[2]);
    shadowLoopers[3] =
        new SkBlurDrawLooper (SkIntToScalar(5), SkIntToScalar(-5),
                              SkIntToScalar(-10), 0x7FFF0000,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag  );
    SkAutoUnref aurL3(shadowLoopers[3]);
    shadowLoopers[4] =
        new SkBlurDrawLooper (SkIntToScalar(0), SkIntToScalar(5),
                              SkIntToScalar(5), 0xFF000000,
                              SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
                              SkBlurDrawLooper::kOverrideColor_BlurFlag |
                              SkBlurDrawLooper::kHighQuality_BlurFlag  );
    SkAutoUnref aurL4(shadowLoopers[4]);

    static const struct {
        SkColor fColor;
        SkScalar fStrokeWidth;
    } gRec[] = {
        { SK_ColorRED,      -SK_Scalar1 },
        { SK_ColorGREEN,    SkIntToScalar(4) },
    };

    SkPaint paint;
    paint.setAntiAlias(true);
    for (size_t i = 0; i < SK_ARRAY_COUNT(shadowLoopers); ++i) {
        SkAutoCanvasRestore acr(canvas, true);

        paint.setLooper(shadowLoopers[i]);

        canvas->translate(SkIntToScalar(i*40), SkIntToScalar(0));
        setup(&paint, gRec[0].fColor, gRec[0].fStrokeWidth);
        canvas->drawRect(fRect, paint);

        canvas->translate(SkIntToScalar(0), SkIntToScalar(40));
        setup(&paint, gRec[1].fColor, gRec[1].fStrokeWidth);
        canvas->drawPath(fCirclePath, paint);
    }
}

private:
    typedef GM INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

static GM* MyFactory(void*) { return new ShadowsGM; }
static GMRegistry reg(MyFactory);

}
<|endoftext|>


<commit_before>// ast-dump.cc -- AST debug dump.    -*- C++ -*-

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "go-system.h"

#include <iostream>
#include <fstream>

#include "gogo.h"
#include "expressions.h"
#include "statements.h"
#include "types.h"
#include "ast-dump.h"
#include "go-c.h"
#include "go-dump.h"

// The -fgo-dump-ast flag to activate AST dumps.

Go_dump ast_dump_flag("ast");

// This class is used to traverse the tree to look for blocks and
// function headers.

class Ast_dump_traverse_blocks_and_functions : public Traverse
{
 public:
  Ast_dump_traverse_blocks_and_functions(Ast_dump_context* ast_dump_context)
      : Traverse(traverse_blocks | traverse_functions),
      ast_dump_context_(ast_dump_context)
  { }

 protected:
  int
  block(Block*);

  int
  function(Named_object*);

 private:
  Ast_dump_context* ast_dump_context_;
};

// This class is used to traverse the tree to look for statements.

class Ast_dump_traverse_statements : public Traverse
{
 public:
  Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context)
      : Traverse(traverse_statements),
      ast_dump_context_(ast_dump_context)
  { }

 protected:
  int
  statement(Block*, size_t* pindex, Statement*);

 private:
  Ast_dump_context* ast_dump_context_;
};

// For each block we enclose it in brackets.

int Ast_dump_traverse_blocks_and_functions::block(Block * block)
{
  if (block == NULL)
    {
      this->ast_dump_context_->ostream() << std::endl;
      return TRAVERSE_EXIT;
    }

  this->ast_dump_context_->print_indent();
  this->ast_dump_context_->ostream() << "{" << std::endl;
  this->ast_dump_context_->indent();

  // Dump statememts.
  Ast_dump_traverse_statements adts(this->ast_dump_context_);
  block->traverse(&adts);

  this->ast_dump_context_->unindent();
  this->ast_dump_context_->print_indent();
  this->ast_dump_context_->ostream() << "}" << std::endl;

  return TRAVERSE_SKIP_COMPONENTS;
}

// Dump each traversed statement.

int
Ast_dump_traverse_statements::statement(Block* block, size_t* pindex,
                                        Statement* statement)
{
  statement->dump_statement(this->ast_dump_context_);

  if (statement->is_block_statement())
    {
      Ast_dump_traverse_blocks_and_functions adtbf(this->ast_dump_context_);
      statement->traverse(block, pindex, &adtbf);
    }

  return TRAVERSE_SKIP_COMPONENTS;
}

// Dump the function header.

int
Ast_dump_traverse_blocks_and_functions::function(Named_object* no)
{
  this->ast_dump_context_->ostream() << no->name();

  go_assert(no->is_function());
  Function* func = no->func_value();

  this->ast_dump_context_->ostream() << "(";
  this->ast_dump_context_->dump_typed_identifier_list(
                              func->type()->parameters());

  this->ast_dump_context_->ostream() << ")";

  Function::Results* res = func->result_variables();
  if (res != NULL && !res->empty())
    {
      this->ast_dump_context_->ostream() << " (";

      for (Function::Results::const_iterator it = res->begin();
          it != res->end();
          it++)
        {
          if (it != res->begin())
            this->ast_dump_context_->ostream() << ",";
          Named_object* no = (*it);

          this->ast_dump_context_->ostream() << no->name() << " ";
          go_assert(no->is_result_variable());
          Result_variable* resvar = no->result_var_value();

          this->ast_dump_context_->dump_type(resvar->type());

        }
      this->ast_dump_context_->ostream() << ")";
    }

  this->ast_dump_context_->ostream() << " : ";
  this->ast_dump_context_->dump_type(func->type());
  this->ast_dump_context_->ostream() << std::endl;

  return TRAVERSE_CONTINUE;
}

// Class Ast_dump_context.

Ast_dump_context::Ast_dump_context(std::ostream* out /* = NULL */,
				   bool dump_subblocks /* = true */)
  :  indent_(0), dump_subblocks_(dump_subblocks), ostream_(out), gogo_(NULL)
{
}

// Dump files will be named %basename%.dump.ast

const char* kAstDumpFileExtension = ".dump.ast";

// Dump the internal representation.

void
Ast_dump_context::dump(Gogo* gogo, const char* basename)
{
  std::ofstream* out = new std::ofstream();
  std::string dumpname(basename);
  dumpname += ".dump.ast";
  out->open(dumpname.c_str());

  if (out->fail())
    {
      error("cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str());
      return;
    }

  this->gogo_ = gogo;
  this->ostream_ = out;

  Ast_dump_traverse_blocks_and_functions adtbf(this);
  gogo->traverse(&adtbf);

  out->close();
}

// Dump a textual representation of a type to the
// the dump file.

void
Ast_dump_context::dump_type(const Type* t)
{
  if (t == NULL)
    this->ostream() << "(nil type)";
  else
    // FIXME: write a type pretty printer instead of
    // using mangled names.
    if (this->gogo_ != NULL)
      this->ostream() << "(" << t->mangled_name(this->gogo_) <<  ")";
}

// Dump a textual representation of a block to the
// the dump file.

void
Ast_dump_context::dump_block(Block* b)
{
  Ast_dump_traverse_blocks_and_functions adtbf(this);
  b->traverse(&adtbf);
}

// Dump a textual representation of an expression to the
// the dump file.

void
Ast_dump_context::dump_expression(const Expression* e)
{
  e->dump_expression(this);
}

// Dump a textual representation of an expression list to the
// the dump file.

void
Ast_dump_context::dump_expression_list(const Expression_list* el,
				       bool as_pairs /* = false */)
{
  if (el == NULL)
    return;

  for (std::vector<Expression*>::const_iterator it = el->begin();
       it != el->end();
       it++)
    {
      if ( it != el->begin())
        this->ostream() << ",";
      if (*it != NULL)
	(*it)->dump_expression(this);
      else
        this->ostream() << "NULL";
      if (as_pairs)
        {
	  this->ostream() << ":";
	  ++it;
	  (*it)->dump_expression(this);
        }
    }
}

// Dump a textual representation of a typed identifier to the
// the dump file.

void
Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
{
  this->ostream() << ti->name() << " ";
  this->dump_type(ti->type());
}

// Dump a textual representation of a typed identifier list to the
// the dump file.

void
Ast_dump_context::dump_typed_identifier_list(
    const Typed_identifier_list* ti_list)
{
  if (ti_list == NULL)
    return;

  for (Typed_identifier_list::const_iterator it = ti_list->begin();
       it != ti_list->end();
       it++)
    {
      if (it != ti_list->begin())
        this->ostream() << ",";
      this->dump_typed_identifier(&(*it));
    }
}

// Dump a textual representation of a temporary variable to the
// the dump file.

void
Ast_dump_context::dump_temp_variable_name(const Statement* s)
{
  go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
  // Use the statement address as part of the name for the temporary variable.
  this->ostream() << "tmp." << (uintptr_t) s;
}

// Dump a textual representation of a label to the
// the dump file.

void
Ast_dump_context::dump_label_name(const Unnamed_label* l)
{
  // Use the unnamed label address as part of the name for the temporary
  // variable.
  this->ostream() << "label." << (uintptr_t) l;
}

// Produce a textual representation of an operator symbol.

static const char*
op_string(Operator op)
{
// FIXME: This should be in line with symbols that are parsed,
// exported and/or imported.
  switch (op)
    {
    case OPERATOR_PLUS:
      return "+";
    case OPERATOR_MINUS:
      return "-";
    case OPERATOR_NOT:
      return "!";
    case OPERATOR_XOR:
      return "^";
    case OPERATOR_OR:
      return "|";
    case OPERATOR_AND:
      return "&";
    case OPERATOR_MULT:
      return "*";
    case OPERATOR_OROR:
      return "||";
    case OPERATOR_ANDAND:
      return "&&";
    case OPERATOR_EQEQ:
      return "==";
    case OPERATOR_NOTEQ:
      return "!=";
    case OPERATOR_LT:
      return "<";
    case OPERATOR_LE:
      return "<=";
    case OPERATOR_GT:
      return ">";
    case OPERATOR_GE:
      return ">=";
    case OPERATOR_DIV:
      return "/";
    case OPERATOR_MOD:
      return "%";
    case OPERATOR_LSHIFT:
      return "<<";
    case OPERATOR_RSHIFT:
      return "//";
    case OPERATOR_BITCLEAR:
      return "&^";
    case OPERATOR_CHANOP:
      return "<-";
    case OPERATOR_PLUSEQ:
      return "+=";
    case OPERATOR_MINUSEQ:
      return "-=";
    case OPERATOR_OREQ:
      return "|=";
    case OPERATOR_XOREQ:
      return "^=";
    case OPERATOR_MULTEQ:
      return "*=";
    case OPERATOR_DIVEQ:
      return "/=";
    case OPERATOR_MODEQ:
      return "%=";
    case OPERATOR_LSHIFTEQ:
      return "<<=";
    case OPERATOR_RSHIFTEQ:
      return ">>=";
    case OPERATOR_ANDEQ:
      return "&=";
    case OPERATOR_BITCLEAREQ:
      return "&^=";
    case OPERATOR_PLUSPLUS:
      return "++";
    case OPERATOR_MINUSMINUS:
      return "--";
    case OPERATOR_COLON:
      return ":";
    case OPERATOR_COLONEQ:
      return ":=";
    case OPERATOR_SEMICOLON:
      return ";";
    case OPERATOR_DOT:
      return ".";
    case OPERATOR_ELLIPSIS:
      return "...";
    case OPERATOR_COMMA:
      return ",";
    case OPERATOR_LPAREN:
      return "(";
    case OPERATOR_RPAREN:
      return ")";
    case OPERATOR_LCURLY:
      return "{";
    case OPERATOR_RCURLY:
      return "}";
    case OPERATOR_LSQUARE:
      return "[";
    case OPERATOR_RSQUARE:
      return "]";
    default:
      go_unreachable();
    }
  return NULL;
}

// Dump a textual representation of an operator to the
// the dump file.

void
Ast_dump_context::dump_operator(Operator op)
{
  this->ostream() << op_string(op);
}

// Size of a single indent.

const int Ast_dump_context::offset_ = 2;

// Print indenting spaces to dump file.

void
Ast_dump_context::print_indent()
{
  for (int i = 0; i < this->indent_ * this->offset_; i++)
    this->ostream() << " ";
}

// Dump a textual representation of the ast to the
// the dump file.

void Gogo::dump_ast(const char* basename)
{
  if (::ast_dump_flag.is_enabled())
    {
      Ast_dump_context adc;
      adc.dump(this, basename);
    }
}

// Implementation of String_dump interface.

void
Ast_dump_context::write_c_string(const char* s)
{
  this->ostream() << s;
}

void
Ast_dump_context::write_string(const std::string& s)
{
  this->ostream() << s;
}

// Dump statment to stream.

void
Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
{
  Ast_dump_context adc(out, false);
  stm->dump_statement(&adc);
}

// Dump expression to stream.

void
Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
{
  Ast_dump_context adc(out, false);
  expr->dump_expression(&adc);
}
<commit_msg>compiler: allocate std::ofstream as a local variable<commit_after>// ast-dump.cc -- AST debug dump.    -*- C++ -*-

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "go-system.h"

#include <iostream>
#include <fstream>

#include "gogo.h"
#include "expressions.h"
#include "statements.h"
#include "types.h"
#include "ast-dump.h"
#include "go-c.h"
#include "go-dump.h"

// The -fgo-dump-ast flag to activate AST dumps.

Go_dump ast_dump_flag("ast");

// This class is used to traverse the tree to look for blocks and
// function headers.

class Ast_dump_traverse_blocks_and_functions : public Traverse
{
 public:
  Ast_dump_traverse_blocks_and_functions(Ast_dump_context* ast_dump_context)
      : Traverse(traverse_blocks | traverse_functions),
      ast_dump_context_(ast_dump_context)
  { }

 protected:
  int
  block(Block*);

  int
  function(Named_object*);

 private:
  Ast_dump_context* ast_dump_context_;
};

// This class is used to traverse the tree to look for statements.

class Ast_dump_traverse_statements : public Traverse
{
 public:
  Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context)
      : Traverse(traverse_statements),
      ast_dump_context_(ast_dump_context)
  { }

 protected:
  int
  statement(Block*, size_t* pindex, Statement*);

 private:
  Ast_dump_context* ast_dump_context_;
};

// For each block we enclose it in brackets.

int Ast_dump_traverse_blocks_and_functions::block(Block * block)
{
  if (block == NULL)
    {
      this->ast_dump_context_->ostream() << std::endl;
      return TRAVERSE_EXIT;
    }

  this->ast_dump_context_->print_indent();
  this->ast_dump_context_->ostream() << "{" << std::endl;
  this->ast_dump_context_->indent();

  // Dump statememts.
  Ast_dump_traverse_statements adts(this->ast_dump_context_);
  block->traverse(&adts);

  this->ast_dump_context_->unindent();
  this->ast_dump_context_->print_indent();
  this->ast_dump_context_->ostream() << "}" << std::endl;

  return TRAVERSE_SKIP_COMPONENTS;
}

// Dump each traversed statement.

int
Ast_dump_traverse_statements::statement(Block* block, size_t* pindex,
                                        Statement* statement)
{
  statement->dump_statement(this->ast_dump_context_);

  if (statement->is_block_statement())
    {
      Ast_dump_traverse_blocks_and_functions adtbf(this->ast_dump_context_);
      statement->traverse(block, pindex, &adtbf);
    }

  return TRAVERSE_SKIP_COMPONENTS;
}

// Dump the function header.

int
Ast_dump_traverse_blocks_and_functions::function(Named_object* no)
{
  this->ast_dump_context_->ostream() << no->name();

  go_assert(no->is_function());
  Function* func = no->func_value();

  this->ast_dump_context_->ostream() << "(";
  this->ast_dump_context_->dump_typed_identifier_list(
                              func->type()->parameters());

  this->ast_dump_context_->ostream() << ")";

  Function::Results* res = func->result_variables();
  if (res != NULL && !res->empty())
    {
      this->ast_dump_context_->ostream() << " (";

      for (Function::Results::const_iterator it = res->begin();
          it != res->end();
          it++)
        {
          if (it != res->begin())
            this->ast_dump_context_->ostream() << ",";
          Named_object* no = (*it);

          this->ast_dump_context_->ostream() << no->name() << " ";
          go_assert(no->is_result_variable());
          Result_variable* resvar = no->result_var_value();

          this->ast_dump_context_->dump_type(resvar->type());

        }
      this->ast_dump_context_->ostream() << ")";
    }

  this->ast_dump_context_->ostream() << " : ";
  this->ast_dump_context_->dump_type(func->type());
  this->ast_dump_context_->ostream() << std::endl;

  return TRAVERSE_CONTINUE;
}

// Class Ast_dump_context.

Ast_dump_context::Ast_dump_context(std::ostream* out /* = NULL */,
				   bool dump_subblocks /* = true */)
  :  indent_(0), dump_subblocks_(dump_subblocks), ostream_(out), gogo_(NULL)
{
}

// Dump files will be named %basename%.dump.ast

const char* kAstDumpFileExtension = ".dump.ast";

// Dump the internal representation.

void
Ast_dump_context::dump(Gogo* gogo, const char* basename)
{
  std::ofstream out;
  std::string dumpname(basename);
  dumpname += ".dump.ast";
  out.open(dumpname.c_str());

  if (out.fail())
    {
      error("cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str());
      return;
    }

  this->gogo_ = gogo;
  this->ostream_ = &out;

  Ast_dump_traverse_blocks_and_functions adtbf(this);
  gogo->traverse(&adtbf);

  out.close();
}

// Dump a textual representation of a type to the
// the dump file.

void
Ast_dump_context::dump_type(const Type* t)
{
  if (t == NULL)
    this->ostream() << "(nil type)";
  else
    // FIXME: write a type pretty printer instead of
    // using mangled names.
    if (this->gogo_ != NULL)
      this->ostream() << "(" << t->mangled_name(this->gogo_) <<  ")";
}

// Dump a textual representation of a block to the
// the dump file.

void
Ast_dump_context::dump_block(Block* b)
{
  Ast_dump_traverse_blocks_and_functions adtbf(this);
  b->traverse(&adtbf);
}

// Dump a textual representation of an expression to the
// the dump file.

void
Ast_dump_context::dump_expression(const Expression* e)
{
  e->dump_expression(this);
}

// Dump a textual representation of an expression list to the
// the dump file.

void
Ast_dump_context::dump_expression_list(const Expression_list* el,
				       bool as_pairs /* = false */)
{
  if (el == NULL)
    return;

  for (std::vector<Expression*>::const_iterator it = el->begin();
       it != el->end();
       it++)
    {
      if ( it != el->begin())
        this->ostream() << ",";
      if (*it != NULL)
	(*it)->dump_expression(this);
      else
        this->ostream() << "NULL";
      if (as_pairs)
        {
	  this->ostream() << ":";
	  ++it;
	  (*it)->dump_expression(this);
        }
    }
}

// Dump a textual representation of a typed identifier to the
// the dump file.

void
Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
{
  this->ostream() << ti->name() << " ";
  this->dump_type(ti->type());
}

// Dump a textual representation of a typed identifier list to the
// the dump file.

void
Ast_dump_context::dump_typed_identifier_list(
    const Typed_identifier_list* ti_list)
{
  if (ti_list == NULL)
    return;

  for (Typed_identifier_list::const_iterator it = ti_list->begin();
       it != ti_list->end();
       it++)
    {
      if (it != ti_list->begin())
        this->ostream() << ",";
      this->dump_typed_identifier(&(*it));
    }
}

// Dump a textual representation of a temporary variable to the
// the dump file.

void
Ast_dump_context::dump_temp_variable_name(const Statement* s)
{
  go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
  // Use the statement address as part of the name for the temporary variable.
  this->ostream() << "tmp." << (uintptr_t) s;
}

// Dump a textual representation of a label to the
// the dump file.

void
Ast_dump_context::dump_label_name(const Unnamed_label* l)
{
  // Use the unnamed label address as part of the name for the temporary
  // variable.
  this->ostream() << "label." << (uintptr_t) l;
}

// Produce a textual representation of an operator symbol.

static const char*
op_string(Operator op)
{
// FIXME: This should be in line with symbols that are parsed,
// exported and/or imported.
  switch (op)
    {
    case OPERATOR_PLUS:
      return "+";
    case OPERATOR_MINUS:
      return "-";
    case OPERATOR_NOT:
      return "!";
    case OPERATOR_XOR:
      return "^";
    case OPERATOR_OR:
      return "|";
    case OPERATOR_AND:
      return "&";
    case OPERATOR_MULT:
      return "*";
    case OPERATOR_OROR:
      return "||";
    case OPERATOR_ANDAND:
      return "&&";
    case OPERATOR_EQEQ:
      return "==";
    case OPERATOR_NOTEQ:
      return "!=";
    case OPERATOR_LT:
      return "<";
    case OPERATOR_LE:
      return "<=";
    case OPERATOR_GT:
      return ">";
    case OPERATOR_GE:
      return ">=";
    case OPERATOR_DIV:
      return "/";
    case OPERATOR_MOD:
      return "%";
    case OPERATOR_LSHIFT:
      return "<<";
    case OPERATOR_RSHIFT:
      return "//";
    case OPERATOR_BITCLEAR:
      return "&^";
    case OPERATOR_CHANOP:
      return "<-";
    case OPERATOR_PLUSEQ:
      return "+=";
    case OPERATOR_MINUSEQ:
      return "-=";
    case OPERATOR_OREQ:
      return "|=";
    case OPERATOR_XOREQ:
      return "^=";
    case OPERATOR_MULTEQ:
      return "*=";
    case OPERATOR_DIVEQ:
      return "/=";
    case OPERATOR_MODEQ:
      return "%=";
    case OPERATOR_LSHIFTEQ:
      return "<<=";
    case OPERATOR_RSHIFTEQ:
      return ">>=";
    case OPERATOR_ANDEQ:
      return "&=";
    case OPERATOR_BITCLEAREQ:
      return "&^=";
    case OPERATOR_PLUSPLUS:
      return "++";
    case OPERATOR_MINUSMINUS:
      return "--";
    case OPERATOR_COLON:
      return ":";
    case OPERATOR_COLONEQ:
      return ":=";
    case OPERATOR_SEMICOLON:
      return ";";
    case OPERATOR_DOT:
      return ".";
    case OPERATOR_ELLIPSIS:
      return "...";
    case OPERATOR_COMMA:
      return ",";
    case OPERATOR_LPAREN:
      return "(";
    case OPERATOR_RPAREN:
      return ")";
    case OPERATOR_LCURLY:
      return "{";
    case OPERATOR_RCURLY:
      return "}";
    case OPERATOR_LSQUARE:
      return "[";
    case OPERATOR_RSQUARE:
      return "]";
    default:
      go_unreachable();
    }
  return NULL;
}

// Dump a textual representation of an operator to the
// the dump file.

void
Ast_dump_context::dump_operator(Operator op)
{
  this->ostream() << op_string(op);
}

// Size of a single indent.

const int Ast_dump_context::offset_ = 2;

// Print indenting spaces to dump file.

void
Ast_dump_context::print_indent()
{
  for (int i = 0; i < this->indent_ * this->offset_; i++)
    this->ostream() << " ";
}

// Dump a textual representation of the ast to the
// the dump file.

void Gogo::dump_ast(const char* basename)
{
  if (::ast_dump_flag.is_enabled())
    {
      Ast_dump_context adc;
      adc.dump(this, basename);
    }
}

// Implementation of String_dump interface.

void
Ast_dump_context::write_c_string(const char* s)
{
  this->ostream() << s;
}

void
Ast_dump_context::write_string(const std::string& s)
{
  this->ostream() << s;
}

// Dump statment to stream.

void
Ast_dump_context::dump_to_stream(const Statement* stm, std::ostream* out)
{
  Ast_dump_context adc(out, false);
  stm->dump_statement(&adc);
}

// Dump expression to stream.

void
Ast_dump_context::dump_to_stream(const Expression* expr, std::ostream* out)
{
  Ast_dump_context adc(out, false);
  expr->dump_expression(&adc);
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
//#include "qt4strigiclient.h"
#include "searchview.h"
#include "strigihtmlgui.h"
#include <QtGui/QVBoxLayout>
#include <QtGui/QTextBrowser>
#include <QtCore/QDebug>
#include <QtCore/QProcess>
#include <QtCore/QFileInfo>
#include <QtCore/QDateTime>
#include <QtCore/QUrl>
#include <QtCore/QVariant>

using namespace std;

class SearchViewHtmlHelper : public HtmlHelper {
private:
    QDateTime time;
public:
    SearchViewHtmlHelper() {}
    ~SearchViewHtmlHelper() {}
    std::string mapLinkUrl(const std::string& url, int depth = 0) {
        return url;
    }
    std::string mapMimetypeIcon(const std::string& url,
            const std::string& mimetype);
    std::string encodeString(const std::string& url);
    std::string escapeString(const std::string& url);
    std::string formatDate(time_t date);
    std::string getCssUrl() { return ":/strigi/result.css"; }
    std::string highlight(const std::string& text,
        const std::vector<std::string>& queryterms);
    std::string mimetypeDescription(const std::string& mimetype) const {
        return mimetype;
    }
};
string
SearchViewHtmlHelper::mapMimetypeIcon(const string& url,
            const string& mimetype) {
    // use gnome icons because they map easily
    QString gnome = "/opt/gnome/share/icons/gnome/48x48/mimetypes/gnome-mime-";
    QString icon(mimetype.c_str());
    icon.replace("/", "-");
    icon = gnome + icon + ".png";
    QFileInfo i(icon);
    QString html;
    if (!i.exists()) {
        icon = "";
    }
    return (const char*)icon.toUtf8();
}
string
SearchViewHtmlHelper::encodeString(const string& url) {
    QUrl u = QUrl::fromEncoded(url.c_str());
    return (const char*)u.toString().toUtf8();
}
string
SearchViewHtmlHelper::escapeString(const string& line) {
    return (const char*)Qt::escape(QString::fromUtf8(line.c_str())).toUtf8();
}
string
SearchViewHtmlHelper::formatDate(time_t date) {
    QDateTime time;
    time.setTime_t(date);
    return (const char*)time.toString().toUtf8();
}
string
SearchViewHtmlHelper::highlight(const std::string& text,
        const std::vector<std::string>& terms) {
    int pre = 5, post = 5;
    int maxlen = 200;
    QString t = QString::fromUtf8(text.c_str(), text.length());
    vector<QRegExp> res;
    QString out;
    for (uint i=0; i<terms.size(); ++i) {
        QString term = QString::fromUtf8(terms[i].c_str(), terms[i].length());
        term.replace('*', "\\w*").replace('?',"\\w");
        res.push_back(QRegExp("\\b("+term+")\\b", Qt::CaseInsensitive));
    }
    int pos = 0;
    int lasts = -1;
    int laste = -1;
    while (pos >= 0 && out.length()+laste-lasts < maxlen) {
        int rep = -1;
        int len = 0;
        for (uint i=0; i<res.size(); ++i) {
            int p = t.indexOf(res[i], pos);
            if (p >= 0 && (rep == -1 || p < rep)) {
                rep = p;
                len = terms[i].length();
            }
        }
        if (rep >= 0) {
            int s = (rep-pre > 0) ?rep-pre :0;
            s = t.lastIndexOf(" ", s);
            if (s == -1) s = (rep-pre < 0) ?0 : rep-pre;
            int e = t.indexOf(" ", rep+len+post);
            if (e == -1) e = t.length();
            if (lasts == -1) {
                lasts = s;
            } else if (s > laste) {
                if (out.length() == 0 && lasts > 0) out += "... ";
                out += t.mid(lasts, laste - lasts) + " ... ";
                lasts = s;
            }
            laste = e;
            pos = rep+1;
        } else {
            pos = rep;
        }
    }
    if (lasts != -1) {
        if (out.length() == 0 && lasts > 0) out += "... ";
        out += t.mid(lasts, laste - lasts) + " ... ";
    }
    for (uint i = 0; i < res.size(); ++i) {
        out.replace(res[i], "\\1");
    }
    if (out.length() == 0) {
        out = t.left(maxlen);
    }
    return (const char*)out.toUtf8();
}
SearchView::SearchView() {
    view = new QTextBrowser();
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->addWidget(view);
    setLayout(layout);
    htmlguihelper = new SearchViewHtmlHelper();
    htmlgui = new StrigiHtmlGui(htmlguihelper);

    connect(&asyncstrigi,
        SIGNAL(gotHits(const QString&, int, const QList<StrigiHit>&)),
        this, SLOT(handleHits(const QString&, int, const QList<StrigiHit>&)));
    connect(view, SIGNAL(anchorClicked(const QUrl&)),
        this, SLOT(openItem(const QUrl&)));
}
SearchView::~SearchView() {
    delete htmlgui;
    delete htmlguihelper;
}
QString str(const string&s) {
    return QString::fromUtf8(s.c_str(), s.length());
}
#include <sstream>
ClientInterface::Hits
toID(const QList<StrigiHit>& hits) {
    ClientInterface::Hits id;
    foreach (const StrigiHit&h, hits) {
        jstreams::IndexedDocument i;
        i.uri.assign(h.uri.toUtf8());
        i.score = h.score;
        i.fragment.assign(h.fragment.toUtf8());
        i.mimetype.assign(h.mimetype.toUtf8());
        i.sha1.assign(h.sha1.toUtf8());
        i.size = h.size;
        i.mtime = h.mtime;
        id.hits.push_back(i);
    }
    return id;
}
void
SearchView::handleHits(const QString& q, int offset,
        const QList<StrigiHit>& hits) {
    view->clear();
    setEnabled(true);
    if (q != query) return;
    QUrl cssurl(":/strigi/result.css");
    QVariant css = "";
    view->document()->addResource(QTextDocument::StyleSheetResource,
        cssurl, css);
    if (hits.size() > 0) {
        ostringstream str;
        ClientInterface::Hits shits = toID(hits);
        htmlgui->printSearchResults(str, shits, (const char*)q.toUtf8());
        QString html(QString::fromUtf8(str.str().c_str()));
        view->setHtml(html);
    } else {
        view->append("no results");
    }
}
void
SearchView::setHTML(const QString& html) {
    view->setHtml(html);
}
void
SearchView::setQuery(const QString& q) {
    query = q;
    asyncstrigi.clearGetQueries();
    asyncstrigi.addGetQuery(query, 10, 0);
}
void
SearchView::openItem(const QUrl& url) {
    // if the file does not exist on the file system remove items of the end
    // until it does
    QString file = QUrl::fromPercentEncoding(url.toString().toAscii());
    view->setSource(view->source());
    QFileInfo info(file);
    while (!info.exists()) {
        int pos = file.lastIndexOf('/');
        if (pos <= 0) return;
        file = file.left(pos);
        info.setFile(file);
    }
    if (file.endsWith(".tar") || file.endsWith(".tar.bz2")
            || file.endsWith(".tar.gz")) {
        file = "tar:"+url.toString();
    } else if (file.endsWith(".zip") || file.endsWith(".jar")) {
        file = "zip:"+url.toString();
    }
    QStringList args;
    args << "exec" << file;
    QProcess::execute("kfmclient", args);
}
<commit_msg>Make better hit text fragments.<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
//#include "qt4strigiclient.h"
#include "searchview.h"
#include "strigihtmlgui.h"
#include <QtGui/QVBoxLayout>
#include <QtGui/QTextBrowser>
#include <QtCore/QDebug>
#include <QtCore/QProcess>
#include <QtCore/QFileInfo>
#include <QtCore/QDateTime>
#include <QtCore/QUrl>
#include <QtCore/QVariant>

using namespace std;

class SearchViewHtmlHelper : public HtmlHelper {
private:
    QDateTime time;
public:
    SearchViewHtmlHelper() {}
    ~SearchViewHtmlHelper() {}
    std::string mapLinkUrl(const std::string& url, int depth = 0) {
        return url;
    }
    std::string mapMimetypeIcon(const std::string& url,
            const std::string& mimetype);
    std::string encodeString(const std::string& url);
    std::string escapeString(const std::string& url);
    std::string formatDate(time_t date);
    std::string getCssUrl() { return ":/strigi/result.css"; }
    std::string highlight(const std::string& text,
        const std::vector<std::string>& queryterms);
    std::string mimetypeDescription(const std::string& mimetype) const {
        return mimetype;
    }
};
string
SearchViewHtmlHelper::mapMimetypeIcon(const string& url,
            const string& mimetype) {
    // use gnome icons because they map easily
    QString gnome = "/opt/gnome/share/icons/gnome/48x48/mimetypes/gnome-mime-";
    QString icon(mimetype.c_str());
    icon.replace("/", "-");
    icon = gnome + icon + ".png";
    QFileInfo i(icon);
    QString html;
    if (!i.exists()) {
        icon = "";
    }
    return (const char*)icon.toUtf8();
}
string
SearchViewHtmlHelper::encodeString(const string& url) {
    QUrl u = QUrl::fromEncoded(url.c_str());
    return (const char*)u.toString().toUtf8();
}
string
SearchViewHtmlHelper::escapeString(const string& line) {
    return (const char*)Qt::escape(QString::fromUtf8(line.c_str())).toUtf8();
}
string
SearchViewHtmlHelper::formatDate(time_t date) {
    QDateTime time;
    time.setTime_t(date);
    return (const char*)time.toString().toUtf8();
}
string
SearchViewHtmlHelper::highlight(const std::string& text,
        const std::vector<std::string>& terms) {
    int pre = 5, post = 5;
    int maxlen = 200;
    QString t = QString::fromUtf8(text.c_str(), text.length());
    vector<QRegExp> res;
    QString out;
    for (uint i=0; i<terms.size(); ++i) {
        QString term = QString::fromUtf8(terms[i].c_str(), terms[i].length());
        term.replace('*', "\\w*").replace('?',"\\w");
        res.push_back(QRegExp("\\b("+term+")\\b", Qt::CaseInsensitive));
    }
    int pos = 0;
    int lasts = -1;
    int laste = -1;
    QRegExp nonword("\\W");
    while (pos >= 0 && out.length()+laste-lasts < maxlen) {
        int rep = -1;
        int len = 0;
        for (uint i=0; i<res.size(); ++i) {
            int p = t.indexOf(res[i], pos);
            if (p >= 0 && (rep == -1 || p < rep)) {
                rep = p;
                len = terms[i].length();
            }
        }
        if (rep >= 0) {
            int s = (rep-pre > 0) ?rep-pre :0;
            s = t.lastIndexOf(nonword, s);
            if (s == -1) s = (rep-pre < 0) ?0 : rep-pre;
            int e = t.indexOf(nonword, rep+len+post);
            if (e == -1) e = t.length();
            if (lasts == -1) {
                lasts = s;
            } else if (s > laste) {
                if (out.length() == 0 && lasts > 0) out += "... ";
                out += t.mid(lasts, laste - lasts) + " ... ";
                lasts = s;
            }
            laste = e;
            pos = rep+1;
        } else {
            pos = rep;
        }
    }
    if (lasts != -1) {
        if (out.length() == 0 && lasts > 0) out += "... ";
        out += t.mid(lasts, laste - lasts) + " ... ";
    }
    for (uint i = 0; i < res.size(); ++i) {
        out.replace(res[i], "\\1");
    }
    if (out.length() == 0) {
        out = t.left(maxlen);
    }
    return (const char*)out.toUtf8();
}
SearchView::SearchView() {
    view = new QTextBrowser();
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->addWidget(view);
    setLayout(layout);
    htmlguihelper = new SearchViewHtmlHelper();
    htmlgui = new StrigiHtmlGui(htmlguihelper);

    connect(&asyncstrigi,
        SIGNAL(gotHits(const QString&, int, const QList<StrigiHit>&)),
        this, SLOT(handleHits(const QString&, int, const QList<StrigiHit>&)));
    connect(view, SIGNAL(anchorClicked(const QUrl&)),
        this, SLOT(openItem(const QUrl&)));
}
SearchView::~SearchView() {
    delete htmlgui;
    delete htmlguihelper;
}
QString str(const string&s) {
    return QString::fromUtf8(s.c_str(), s.length());
}
#include <sstream>
ClientInterface::Hits
toID(const QList<StrigiHit>& hits) {
    ClientInterface::Hits id;
    foreach (const StrigiHit&h, hits) {
        jstreams::IndexedDocument i;
        i.uri.assign(h.uri.toUtf8());
        i.score = h.score;
        i.fragment.assign(h.fragment.toUtf8());
        i.mimetype.assign(h.mimetype.toUtf8());
        i.sha1.assign(h.sha1.toUtf8());
        i.size = h.size;
        i.mtime = h.mtime;
        id.hits.push_back(i);
    }
    return id;
}
void
SearchView::handleHits(const QString& q, int offset,
        const QList<StrigiHit>& hits) {
    view->clear();
    setEnabled(true);
    if (q != query) return;
    QUrl cssurl(":/strigi/result.css");
    QVariant css = "";
    view->document()->addResource(QTextDocument::StyleSheetResource,
        cssurl, css);
    if (hits.size() > 0) {
        ostringstream str;
        ClientInterface::Hits shits = toID(hits);
        htmlgui->printSearchResults(str, shits, (const char*)q.toUtf8());
        QString html(QString::fromUtf8(str.str().c_str()));
        view->setHtml(html);
    } else {
        view->append("no results");
    }
}
void
SearchView::setHTML(const QString& html) {
    view->setHtml(html);
}
void
SearchView::setQuery(const QString& q) {
    query = q;
    asyncstrigi.clearGetQueries();
    asyncstrigi.addGetQuery(query, 10, 0);
}
void
SearchView::openItem(const QUrl& url) {
    // if the file does not exist on the file system remove items of the end
    // until it does
    QString file = QUrl::fromPercentEncoding(url.toString().toAscii());
    view->setSource(view->source());
    QFileInfo info(file);
    while (!info.exists()) {
        int pos = file.lastIndexOf('/');
        if (pos <= 0) return;
        file = file.left(pos);
        info.setFile(file);
    }
    if (file.endsWith(".tar") || file.endsWith(".tar.bz2")
            || file.endsWith(".tar.gz")) {
        file = "tar:"+url.toString();
    } else if (file.endsWith(".zip") || file.endsWith(".jar")) {
        file = "zip:"+url.toString();
    }
    QStringList args;
    args << "exec" << file;
    QProcess::execute("kfmclient", args);
}
<|endoftext|>


<commit_before>#include <sh/sh.hpp>
#include <sh/shutil.hpp>
#include <iostream>
#include "Shader.hpp"
#include "Globals.hpp"

using namespace SH;
using namespace ShUtil;

class Lafortune : public Shader {
public:
  Lafortune();
  ~Lafortune();

  bool init();

  ShProgram vertex() { return vsh;}
  ShProgram fragment() { return fsh;}

  ShProgram vsh, fsh;

  static Lafortune instance;
};

Lafortune::Lafortune()
  : Shader("Basic Lighting Models: Lafortune")
{
}

Lafortune::~Lafortune()
{
}

bool Lafortune::init()
{
  vsh = SH_BEGIN_PROGRAM("gpu:vertex") {
    ShInputPosition4f ipos;
    ShInputNormal3f inorm;
		ShInputVector3f itan;

    ShOutputPosition4f opos; // Position in NDC
    ShInOutTexCoord2f tc; // pass through tex coords
    ShOutputNormal3f onorm;
		ShOutputVector3f otan;
		ShOutputVector3f osurf;
    ShOutputVector3f lightv; // direction to light
		ShOutputVector3f viewv;

    opos = Globals::mvp | ipos; // Compute NDC position
    onorm = Globals::mv | inorm; // Compute view-space normal
		otan = Globals::mv | itan; // Compute view-space tangent
		osurf = cross(onorm,otan);
    ShPoint3f posv = (Globals::mv | ipos)(0,1,2); // Compute view-space position
    lightv = normalize(Globals::lightPos - posv); // Compute light direction
    ShPoint3f eye = -normalize(posv); // view vector
    viewv = normalize(eye - posv);

  } SH_END;

  ShColor3f SH_DECL(specular) = ShColor3f(0.5, 1.0, 1.0);
  ShColor3f SH_DECL(diffuse) = ShColor3f(1.0, 0.0, 0.0);

	ShAttrib3f SH_DECL(D) = ShAttrib3f(-1.0,1.0,1.0);
	D.range(-10.0,10.0);

  ShAttrib1f SH_DECL(exponent) = ShAttrib1f(35.0);
  exponent.range(5.0f, 500.0f);

  fsh = SH_BEGIN_PROGRAM("gpu:fragment") {
    ShInputPosition4f posh;
    ShInputTexCoord2f tc;
    ShInputNormal3f normal;
		ShInputVector3f tangent;
		ShInputVector3f surface;
    ShInputVector3f light;
		ShInputVector3f view;

    ShOutputColor3f result;

    normal = normalize(normal);
		tangent = normalize(tangent);
		surface = normalize(surface);
    light = normalize(light);

		ShVector3f lS = ShVector3f(D(0)*light|tangent, D(1)*light|surface, D(2)*light|normal);
		ShVector3f vS = ShVector3f(view|tangent, view|surface, view|normal);

    // Compute phong lighting.
    ShAttrib1f irrad = pos(normal | light);
		result = diffuse*irrad + specular*pow((lS|vS), exponent);

  } SH_END;
  return true;
}

Lafortune Lafortune::instance = Lafortune();

<commit_msg>correction of an initial value problem for the matrix D correction of the pow which was using a negative argument for some values of D<commit_after>#include <sh/sh.hpp>
#include <sh/shutil.hpp>
#include <iostream>
#include "Shader.hpp"
#include "Globals.hpp"

using namespace SH;
using namespace ShUtil;

class Lafortune : public Shader {
public:
  Lafortune();
  ~Lafortune();

  bool init();

  ShProgram vertex() { return vsh;}
  ShProgram fragment() { return fsh;}

  ShProgram vsh, fsh;

  static Lafortune instance;
};

Lafortune::Lafortune()
  : Shader("Basic Lighting Models: Lafortune")
{
}

Lafortune::~Lafortune()
{
}

bool Lafortune::init()
{
  vsh = SH_BEGIN_PROGRAM("gpu:vertex") {
    ShInputPosition4f ipos;
    ShInputNormal3f inorm;
		ShInputVector3f itan;

    ShOutputPosition4f opos; // Position in NDC
    ShInOutTexCoord2f tc; // pass through tex coords
    ShOutputNormal3f onorm;
		ShOutputVector3f otan;
		ShOutputVector3f osurf;
    ShOutputVector3f lightv; // direction to light
		ShOutputVector3f viewv;

    opos = Globals::mvp | ipos; // Compute NDC position
    onorm = Globals::mv | inorm; // Compute view-space normal
		otan = Globals::mv | itan; // Compute view-space tangent
		osurf = cross(onorm,otan);
    ShPoint3f posv = (Globals::mv | ipos)(0,1,2); // Compute view-space position
    lightv = normalize(Globals::lightPos - posv); // Compute light direction
    ShPoint3f eye = -normalize(posv); // view vector
    viewv = normalize(eye - posv);

  } SH_END;

  ShColor3f SH_DECL(specular) = ShColor3f(0.5, 1.0, 1.0);
  ShColor3f SH_DECL(diffuse) = ShColor3f(1.0, 0.0, 0.0);

	ShAttrib3f SH_DECL(D) = ShAttrib3f(0.0,0.0,1.0);
	D.range(-5.0,5.0);

  ShAttrib1f SH_DECL(exponent) = ShAttrib1f(35.0);
  exponent.range(1.0f, 500.0f);

  fsh = SH_BEGIN_PROGRAM("gpu:fragment") {
    ShInputPosition4f posh;
    ShInputTexCoord2f tc;
    ShInputNormal3f normal;
		ShInputVector3f tangent;
		ShInputVector3f surface;
    ShInputVector3f light;
		ShInputVector3f view;

    ShOutputColor3f result;

    normal = normalize(normal);
		tangent = normalize(tangent);
		surface = normalize(surface);
    light = normalize(light);

		ShVector3f lS = ShVector3f(light|tangent, light|surface, light|normal);
		lS *= D;
		ShVector3f vS = ShVector3f(view|tangent, view|surface, view|normal);

    // Compute phong lighting.
    ShAttrib1f irrad = pos(normal | light);
		result = diffuse*irrad + specular*pow(pos(lS|vS), exponent);

  } SH_END;
  return true;
}

Lafortune Lafortune::instance = Lafortune();

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/compress/gzip/Gzipper.h"
#include "db/logging/FileLogger.h"
#include "db/io/FileList.h"
#include "db/io/FileInputStream.h"
#include "db/io/FileOutputStream.h"
#include "db/io/MutatorInputStream.h"
#include "db/rt/Exception.h"
#include "db/rt/RunnableDelegate.h"
#include "db/util/Math.h"
#include "db/util/regex/Pattern.h"

#include <vector>
#include <algorithm>

using namespace std;
using namespace db::compress::gzip;
using namespace db::logging;
using namespace db::io;
using namespace db::rt;
using namespace db::util;
using namespace db::util::regex;

#define DEFAULT_MAX_ROTATED_FILES 5
#define DEFAULT_COMPRESSION_THREAD_POOL_SIZE 2
//#define FILE_LOGGER_DEBUG

FileLogger::FileLogger(File* file) :
   OutputStreamLogger(),
   mFile((FileImpl*)NULL),
   mRotationFileSize(0),
   mCurrentFileSize(0),
   mMaxRotatedFiles(DEFAULT_MAX_ROTATED_FILES),
   mSeqNum(0)
{
   if(file != NULL)
   {
      bool set = setFile(*file, false);
      // FIXME: what to do on exception?
      if(!set)
      {
         Exception::clearLast();
      }
   }
   mCompressionJobDispatcher.getThreadPool()->
      setPoolSize(DEFAULT_COMPRESSION_THREAD_POOL_SIZE);
   mCompressionJobDispatcher.startDispatching();
}

FileLogger::~FileLogger()
{
   // wait for all queued and running compression jobs to finish
   mCompressionWaitLock.lock();
   {
      while(mCompressionJobDispatcher.getTotalJobCount() > 0)
      {
         mCompressionWaitLock.wait();
      }
   }
   mCompressionWaitLock.unlock();

   mCompressionJobDispatcher.stopDispatching();
   close();
}

void FileLogger::close()
{
   mLock.lock();
   {
      OutputStreamLogger::close();
   }
   mLock.unlock();
}

/**
 * Find first available path pair of the form:
 *    "base[-seq]ext"
 * and optionally also a secondary path of the form:
 *    "base[-seq]ext[ext2]"
 *
 * This can be used, for instance, to move a log file to the .ext.ext2 file,
 * create a new source file, then run a compression thread to compress the
 * .ext,ext2 file to the .ext file.
 *
 * Using alphanumericly sortable encoding for sequence of:
 *   seq = chr(ord('a')+len(str(n))-1) + str(n)
 * (ie, prefix decimal string with letter based on length of string)
 *
 * @param base base path
 * @param seq sequence number to use
 * @param ext first file extension
 * @param path primary output path
 * @param ext2 second file extension
 * @param path2 secondary output path
 * @return true if found, false and exception set if not or search failed
 */
static bool findAvailablePath(
   const char* base, unsigned int& seq,
   const char* ext = NULL,
   string* path = NULL,
   const char* ext2 = NULL,
   string* path2 = NULL)
{
   bool found = false;
   size_t seqlen = 20;
   size_t buflen = strlen(base) + seqlen + (ext == NULL ? 0 : strlen(ext)) + 1;
   char buf[buflen];
   size_t buflen2 = buflen + (ext2 == NULL ? 0 : strlen(ext2));
   char buf2[buflen2];
   while(!found)
   {
      // check basic file
      {
         snprintf(buf, buflen, "%s%s", base, ext);
         File f(buf);
         found = !f->exists();
      }
      // handle sub-second file names
      if(!found)
      {
         char seqbuf[seqlen];
         // scan file names until we find a free one
         // FIXME limit this search and fail w/ exception
         while(!found)
         {
            snprintf(seqbuf, seqlen, "%u", seq++);
            char seqc = 'a' + strlen(seqbuf) - 1;
            snprintf(buf, buflen, "%s-%c%s%s",
               base, seqc, seqbuf, (ext == NULL ? "" : ext));
            File f(buf);
            found = !f->exists();
         }
      }
      // check secondary file if needed
      if(found && ext2 != NULL)
      {
         snprintf(buf2, buflen2, "%s%s", buf, ext2);
         File f2(buf2);
         found = !f2->exists();
         printf("buf2[%d]: %s\n", found, buf2);
      }
   }

   if(found)
   {
      // reset sequence
      seq = 0;
      // assign output paths
      if(path != NULL)
      {
         path->assign(buf);
      }
      if(ext2 != NULL && path2 != NULL)
      {
         path2->assign(buf2);
      }
   }

   return found;
}

/**
 * Simple private holder for gzip compression RunnableDelegate info.
 */
class GzipCompressInfo
{
public:
   string sourceFileName;
   string targetFileName;
   GzipCompressInfo() {}
   virtual ~GzipCompressInfo() {}
};

void FileLogger::gzipCompress(void* info)
{
   bool rval;
   GzipCompressInfo* cInfo = (GzipCompressInfo*)info;
   Gzipper gzipper;
   rval = gzipper.startCompressing();

   if(rval)
   {
      File sourceFile(cInfo->sourceFileName.c_str());
      File targetFile(cInfo->targetFileName.c_str());

#ifdef FILE_LOGGER_DEBUG
      printf("FileLogger: z start: %s => %s\n",
         sourceFile->getPath(), targetFile->getPath());
#endif

      FileInputStream fis(sourceFile);
      FileOutputStream fos(targetFile);

      MutatorInputStream mis(&fis, false, &gzipper, false);
      char b[4096];
      int numBytes;
      while(rval && (numBytes = mis.read(b, 4096)) > 0)
      {
         rval = fos.write(b, numBytes);
      }

      fis.close();
      fos.close();

      // done with source
      sourceFile->remove();

#ifdef FILE_LOGGER_DEBUG
      printf("FileLogger: z done: %s => %s\n",
         sourceFile->getPath(), targetFile->getPath());
#endif
   }
   else
   {
#ifdef FILE_LOGGER_DEBUG
      printf("FileLogger: z error\n");
#endif
   }

   delete cInfo;

   // notification for threads that wait for compression to complete
   mCompressionWaitLock.lock();
   {
      mCompressionWaitLock.notifyAll();
   }
   mCompressionWaitLock.unlock();

   // failures and exceptions ignored
}

bool FileLogger::rotate()
{
   bool rval = true;

   // assuming we are locked here
   // get new name
   string date;
   Date now;
   date = now.format(date, ".%Y%m%d%H%M%S");
   string fn;
   fn.assign(mFile->getPath());
   fn.append(date);

   // move file to new name
   close();
   if(getFlags() & GzipCompressRotatedLogs)
   {
      // deleted in gzipCompress or below after setup failure
      GzipCompressInfo* info = new GzipCompressInfo;
      // compress stream from old file to new .gz file
      rval = findAvailablePath(fn.c_str(), mSeqNum,
         ".gz", &info->targetFileName,
         ".orig", &info->sourceFileName);

      // ensure files are created so next findAvailablePath call will pick a
      // correct name regardless of compression thread progress
      if(rval)
      {
         // move source file to new name
         File orig(info->sourceFileName.c_str());
#ifdef FILE_LOGGER_DEBUG
         printf("FileLogger: z rename: %s => %s\n",
            mFile->getPath(), orig->getPath());
#endif
         rval = mFile->rename(orig);
      }
      if(rval)
      {
         // create target file
         File newFile(info->targetFileName.c_str());
#ifdef FILE_LOGGER_DEBUG
         printf("FileLogger: z create: %s\n", newFile->getPath());
#endif
         rval = newFile->create();
      }
      if(rval)
      {
         // send a compression job to the pool
         RunnableRef compressor = new RunnableDelegate<FileLogger>(
            this, &FileLogger::gzipCompress, info);
         mCompressionJobDispatcher.queueJob(compressor);
      }
      else
      {
         delete info;
      }
   }
   else
   {
      // move old file to new file
      string newfn;
      rval = findAvailablePath(fn.c_str(), mSeqNum, "", &newfn);
      if(rval)
      {
         File newFile(newfn.c_str());
#ifdef FILE_LOGGER_DEBUG
         printf("FileLogger: rename: %s => %s\n", fn.c_str(), newfn.c_str());
#endif
         rval = mFile->rename(newFile);
      }
   }

   if(!rval)
   {
      // dump exceptions from moving aside old file
      // FIXME: print exceptoin?
      Exception::clearLast();
      rval = true;
   }

   if(mMaxRotatedFiles > 0)
   {
      // remove old log files
      const char* path = mFile->getAbsolutePath();
      size_t pathlen = strlen(path);

      // build list of files with proper names
      vector<string> oldFiles;
      File dir(File::dirname(path).c_str());
      FileList files;
      dir->listFiles(files);
      IteratorRef<File> i = files->getIterator();
      Pattern* pattern = Pattern::compile(
         "^\\.[0-9]{14}(-[a-z]{1}[0-9]+)?(\\.gz)?$");
      while(i->hasNext())
      {
         File& file = i->next();
         const char* nextpath = file->getAbsolutePath();
         // dummy vars
         unsigned int _start;
         unsigned int _end;
         // check prefix then tail
         if(strncmp(path, nextpath, pathlen) == 0 &&
            pattern->match(nextpath + pathlen, 0, _start, _end))
         {
            oldFiles.push_back(nextpath);
         }
      }
      delete pattern;
      // sort results
      sort(oldFiles.begin(), oldFiles.end());
      // remove if needed
      if(oldFiles.size() > mMaxRotatedFiles)
      {
         vector<string>::size_type last =
            oldFiles.size() - mMaxRotatedFiles;
         for(vector<string>::size_type i = 0; i < last; i++)
         {
            // FIXME: Handle deletion of files in the compression process.
            // Compression jobs may be in a queue to be processed or in process.
            // This removal code may try to remove the target file before the
            // compression has started or completed. This could be handled by
            // keeping track of the jobs associated with file names and
            // stopping the job before it starts or interrupting it.  The
            // compression job should then clean up the orig and gz files. The
            // code below would then not need to be run. As the code is now it
            // may do extra work and/or create files by mistake. They will
            // however be cleaned up next time through this routine. Windows
            // may fail on the remove but will also do cleanup next time this
            // is run.
            File f(oldFiles[i].c_str());
            bool success = f->remove();
#ifdef FILE_LOGGER_DEBUG
            printf("FileLogger: remove: %s\n", f->getPath());
#endif
            // ignore failures
            if(!success)
            {
               Exception::clearLast();
            }
         }
      }
   }

   // start new file
   rval = setFile(mFile, false);

   return rval;
}

bool FileLogger::setFile(File& file, bool append)
{
   bool rval = true;

   mLock.lock();
   {
      close();
      mFile = file;

      if(file->exists())
      {
         if(!append)
         {
            mCurrentFileSize = 0;
            rval = mFile->remove();
         }
         else
         {
            mCurrentFileSize = file->getLength();
         }
      }
      else
      {
         mCurrentFileSize = 0;
      }

      if(rval)
      {
         OutputStream* s = new FileOutputStream(mFile, append);
         setOutputStream(s, true, false);
      }
   }
   mLock.unlock();

   return rval;
}

void FileLogger::setRotationFileSize(uint64_t fileSize)
{
   mLock.lock();
   {
      // 0 is means no maximum log file size
      mRotationFileSize = fileSize;
   }
   mLock.unlock();
}

uint64_t FileLogger::getRotationFileSize()
{
   return mRotationFileSize;
}

void FileLogger::setMaxRotatedFiles(unsigned int maxRotatedFiles)
{
   mLock.lock();
   {
      mMaxRotatedFiles = maxRotatedFiles;
   }
   mLock.unlock();
}

unsigned int FileLogger::getMaxRotatedFiles()
{
   return mMaxRotatedFiles;
}

JobDispatcher& FileLogger::getCompressionJobDispatcher()
{
   return mCompressionJobDispatcher;
}

File& FileLogger::getFile()
{
   return mFile;
}

void FileLogger::log(const char* message, size_t length)
{
   // lock to serialize logs
   mLock.lock();
   {
      mCurrentFileSize += length;
      OutputStreamLogger::log(message, length);
      if(mRotationFileSize != 0 && mCurrentFileSize >= mRotationFileSize)
      {
         bool success = rotate();
         // FIXME how to handle exceptions?
         if(!success)
         {
            Exception::clearLast();
         }
      }
   }
   mLock.unlock();
}
<commit_msg>Add optional long-compress debug code.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/compress/gzip/Gzipper.h"
#include "db/logging/FileLogger.h"
#include "db/io/FileList.h"
#include "db/io/FileInputStream.h"
#include "db/io/FileOutputStream.h"
#include "db/io/MutatorInputStream.h"
#include "db/rt/Exception.h"
#include "db/rt/RunnableDelegate.h"
#include "db/util/Math.h"
#include "db/util/regex/Pattern.h"

#include <vector>
#include <algorithm>

using namespace std;
using namespace db::compress::gzip;
using namespace db::logging;
using namespace db::io;
using namespace db::rt;
using namespace db::util;
using namespace db::util::regex;

#define DEFAULT_MAX_ROTATED_FILES 5
#define DEFAULT_COMPRESSION_THREAD_POOL_SIZE 2
//#define FILE_LOGGER_DEBUG

FileLogger::FileLogger(File* file) :
   OutputStreamLogger(),
   mFile((FileImpl*)NULL),
   mRotationFileSize(0),
   mCurrentFileSize(0),
   mMaxRotatedFiles(DEFAULT_MAX_ROTATED_FILES),
   mSeqNum(0)
{
   if(file != NULL)
   {
      bool set = setFile(*file, false);
      // FIXME: what to do on exception?
      if(!set)
      {
         Exception::clearLast();
      }
   }
   mCompressionJobDispatcher.getThreadPool()->
      setPoolSize(DEFAULT_COMPRESSION_THREAD_POOL_SIZE);
   mCompressionJobDispatcher.startDispatching();
}

FileLogger::~FileLogger()
{
   // wait for all queued and running compression jobs to finish
   mCompressionWaitLock.lock();
   {
      while(mCompressionJobDispatcher.getTotalJobCount() > 0)
      {
         mCompressionWaitLock.wait();
      }
   }
   mCompressionWaitLock.unlock();

   mCompressionJobDispatcher.stopDispatching();
   close();
}

void FileLogger::close()
{
   mLock.lock();
   {
      OutputStreamLogger::close();
   }
   mLock.unlock();
}

/**
 * Find first available path pair of the form:
 *    "base[-seq]ext"
 * and optionally also a secondary path of the form:
 *    "base[-seq]ext[ext2]"
 *
 * This can be used, for instance, to move a log file to the .ext.ext2 file,
 * create a new source file, then run a compression thread to compress the
 * .ext,ext2 file to the .ext file.
 *
 * Using alphanumericly sortable encoding for sequence of:
 *   seq = chr(ord('a')+len(str(n))-1) + str(n)
 * (ie, prefix decimal string with letter based on length of string)
 *
 * @param base base path
 * @param seq sequence number to use
 * @param ext first file extension
 * @param path primary output path
 * @param ext2 second file extension
 * @param path2 secondary output path
 * @return true if found, false and exception set if not or search failed
 */
static bool findAvailablePath(
   const char* base, unsigned int& seq,
   const char* ext = NULL,
   string* path = NULL,
   const char* ext2 = NULL,
   string* path2 = NULL)
{
   bool found = false;
   size_t seqlen = 20;
   size_t buflen = strlen(base) + seqlen + (ext == NULL ? 0 : strlen(ext)) + 1;
   char buf[buflen];
   size_t buflen2 = buflen + (ext2 == NULL ? 0 : strlen(ext2));
   char buf2[buflen2];
   while(!found)
   {
      // check basic file
      {
         snprintf(buf, buflen, "%s%s", base, ext);
         File f(buf);
         found = !f->exists();
      }
      // handle sub-second file names
      if(!found)
      {
         char seqbuf[seqlen];
         // scan file names until we find a free one
         // FIXME limit this search and fail w/ exception
         while(!found)
         {
            snprintf(seqbuf, seqlen, "%u", seq++);
            char seqc = 'a' + strlen(seqbuf) - 1;
            snprintf(buf, buflen, "%s-%c%s%s",
               base, seqc, seqbuf, (ext == NULL ? "" : ext));
            File f(buf);
            found = !f->exists();
         }
      }
      // check secondary file if needed
      if(found && ext2 != NULL)
      {
         snprintf(buf2, buflen2, "%s%s", buf, ext2);
         File f2(buf2);
         found = !f2->exists();
         printf("buf2[%d]: %s\n", found, buf2);
      }
   }

   if(found)
   {
      // reset sequence
      seq = 0;
      // assign output paths
      if(path != NULL)
      {
         path->assign(buf);
      }
      if(ext2 != NULL && path2 != NULL)
      {
         path2->assign(buf2);
      }
   }

   return found;
}

/**
 * Simple private holder for gzip compression RunnableDelegate info.
 */
class GzipCompressInfo
{
public:
   string sourceFileName;
   string targetFileName;
   GzipCompressInfo() {}
   virtual ~GzipCompressInfo() {}
};

void FileLogger::gzipCompress(void* info)
{
   bool rval;
   GzipCompressInfo* cInfo = (GzipCompressInfo*)info;
   Gzipper gzipper;
   rval = gzipper.startCompressing();

   if(rval)
   {
      File sourceFile(cInfo->sourceFileName.c_str());
      File targetFile(cInfo->targetFileName.c_str());

#ifdef FILE_LOGGER_DEBUG
      printf("FileLogger: z start: %s => %s\n",
         sourceFile->getPath(), targetFile->getPath());
#endif

      FileInputStream fis(sourceFile);
      FileOutputStream fos(targetFile);

      MutatorInputStream mis(&fis, false, &gzipper, false);
      char b[4096];
      int numBytes;
      while(rval && (numBytes = mis.read(b, 4096)) > 0)
      {
         rval = fos.write(b, numBytes);
      }

      fis.close();
      fos.close();

      // done with source
      sourceFile->remove();

#ifdef FILE_LOGGER_DEBUG
      //printf("FileLogger: z 1s sleep: %s\n", targetFile->getPath());
      //Thread::sleep(1000);
      printf("FileLogger: z done: %s => %s\n",
         sourceFile->getPath(), targetFile->getPath());
#endif
   }
   else
   {
#ifdef FILE_LOGGER_DEBUG
      printf("FileLogger: z error\n");
#endif
   }

   delete cInfo;

   // notification for threads that wait for compression to complete
   mCompressionWaitLock.lock();
   {
      mCompressionWaitLock.notifyAll();
   }
   mCompressionWaitLock.unlock();

   // failures and exceptions ignored
}

bool FileLogger::rotate()
{
   bool rval = true;

   // assuming we are locked here
   // get new name
   string date;
   Date now;
   date = now.format(date, ".%Y%m%d%H%M%S");
   string fn;
   fn.assign(mFile->getPath());
   fn.append(date);

   // move file to new name
   close();
   if(getFlags() & GzipCompressRotatedLogs)
   {
      // deleted in gzipCompress or below after setup failure
      GzipCompressInfo* info = new GzipCompressInfo;
      // compress stream from old file to new .gz file
      rval = findAvailablePath(fn.c_str(), mSeqNum,
         ".gz", &info->targetFileName,
         ".orig", &info->sourceFileName);

      // ensure files are created so next findAvailablePath call will pick a
      // correct name regardless of compression thread progress
      if(rval)
      {
         // move source file to new name
         File orig(info->sourceFileName.c_str());
#ifdef FILE_LOGGER_DEBUG
         printf("FileLogger: z rename: %s => %s\n",
            mFile->getPath(), orig->getPath());
#endif
         rval = mFile->rename(orig);
      }
      if(rval)
      {
         // create target file
         File newFile(info->targetFileName.c_str());
#ifdef FILE_LOGGER_DEBUG
         printf("FileLogger: z create: %s\n", newFile->getPath());
#endif
         rval = newFile->create();
      }
      if(rval)
      {
         // send a compression job to the pool
         RunnableRef compressor = new RunnableDelegate<FileLogger>(
            this, &FileLogger::gzipCompress, info);
         mCompressionJobDispatcher.queueJob(compressor);
      }
      else
      {
         delete info;
      }
   }
   else
   {
      // move old file to new file
      string newfn;
      rval = findAvailablePath(fn.c_str(), mSeqNum, "", &newfn);
      if(rval)
      {
         File newFile(newfn.c_str());
#ifdef FILE_LOGGER_DEBUG
         printf("FileLogger: rename: %s => %s\n", fn.c_str(), newfn.c_str());
#endif
         rval = mFile->rename(newFile);
      }
   }

   if(!rval)
   {
      // dump exceptions from moving aside old file
      // FIXME: print exceptoin?
      Exception::clearLast();
      rval = true;
   }

   if(mMaxRotatedFiles > 0)
   {
      // remove old log files
      const char* path = mFile->getAbsolutePath();
      size_t pathlen = strlen(path);

      // build list of files with proper names
      vector<string> oldFiles;
      File dir(File::dirname(path).c_str());
      FileList files;
      dir->listFiles(files);
      IteratorRef<File> i = files->getIterator();
      Pattern* pattern = Pattern::compile(
         "^\\.[0-9]{14}(-[a-z]{1}[0-9]+)?(\\.gz)?$");
      while(i->hasNext())
      {
         File& file = i->next();
         const char* nextpath = file->getAbsolutePath();
         // dummy vars
         unsigned int _start;
         unsigned int _end;
         // check prefix then tail
         if(strncmp(path, nextpath, pathlen) == 0 &&
            pattern->match(nextpath + pathlen, 0, _start, _end))
         {
            oldFiles.push_back(nextpath);
         }
      }
      delete pattern;
      // sort results
      sort(oldFiles.begin(), oldFiles.end());
      // remove if needed
      if(oldFiles.size() > mMaxRotatedFiles)
      {
         vector<string>::size_type last =
            oldFiles.size() - mMaxRotatedFiles;
         for(vector<string>::size_type i = 0; i < last; i++)
         {
            // FIXME: Handle deletion of files in the compression process.
            // Compression jobs may be in a queue to be processed or in process.
            // This removal code may try to remove the target file before the
            // compression has started or completed. This could be handled by
            // keeping track of the jobs associated with file names and
            // stopping the job before it starts or interrupting it.  The
            // compression job should then clean up the orig and gz files. The
            // code below would then not need to be run. As the code is now it
            // may do extra work and/or create files by mistake. They will
            // however be cleaned up next time through this routine. Windows
            // may fail on the remove but will also do cleanup next time this
            // is run.
            File f(oldFiles[i].c_str());
            bool success = f->remove();
#ifdef FILE_LOGGER_DEBUG
            printf("FileLogger: remove: %s\n", f->getPath());
#endif
            // ignore failures
            if(!success)
            {
               Exception::clearLast();
            }
         }
      }
   }

   // start new file
   rval = setFile(mFile, false);

   return rval;
}

bool FileLogger::setFile(File& file, bool append)
{
   bool rval = true;

   mLock.lock();
   {
      close();
      mFile = file;

      if(file->exists())
      {
         if(!append)
         {
            mCurrentFileSize = 0;
            rval = mFile->remove();
         }
         else
         {
            mCurrentFileSize = file->getLength();
         }
      }
      else
      {
         mCurrentFileSize = 0;
      }

      if(rval)
      {
         OutputStream* s = new FileOutputStream(mFile, append);
         setOutputStream(s, true, false);
      }
   }
   mLock.unlock();

   return rval;
}

void FileLogger::setRotationFileSize(uint64_t fileSize)
{
   mLock.lock();
   {
      // 0 is means no maximum log file size
      mRotationFileSize = fileSize;
   }
   mLock.unlock();
}

uint64_t FileLogger::getRotationFileSize()
{
   return mRotationFileSize;
}

void FileLogger::setMaxRotatedFiles(unsigned int maxRotatedFiles)
{
   mLock.lock();
   {
      mMaxRotatedFiles = maxRotatedFiles;
   }
   mLock.unlock();
}

unsigned int FileLogger::getMaxRotatedFiles()
{
   return mMaxRotatedFiles;
}

JobDispatcher& FileLogger::getCompressionJobDispatcher()
{
   return mCompressionJobDispatcher;
}

File& FileLogger::getFile()
{
   return mFile;
}

void FileLogger::log(const char* message, size_t length)
{
   // lock to serialize logs
   mLock.lock();
   {
      mCurrentFileSize += length;
      OutputStreamLogger::log(message, length);
      if(mRotationFileSize != 0 && mCurrentFileSize >= mRotationFileSize)
      {
         bool success = rotate();
         // FIXME how to handle exceptions?
         if(!success)
         {
            Exception::clearLast();
         }
      }
   }
   mLock.unlock();
}
<|endoftext|>


<commit_before>#ifndef SIMULATION_GRID_CORE_PROCESS_UTILITY
#define SIMULATION_GRID_CORE_PROCESS_UTILITY

#include <boost/filesystem/path.hpp>

namespace simulation_grid {
namespace core {
namespace process_utility {

#if defined __linux__
boost::filesystem::path current_exe_path();
#endif

} // process_utility
} // namespace core
} // namespace simulation_grid

#endif
<commit_msg>fixed comment<commit_after>#ifndef SIMULATION_GRID_CORE_PROCESS_UTILITY
#define SIMULATION_GRID_CORE_PROCESS_UTILITY

#include <boost/filesystem/path.hpp>

namespace simulation_grid {
namespace core {
namespace process_utility {

#if defined __linux__
boost::filesystem::path current_exe_path();
#endif

} // namespace process_utility
} // namespace core
} // namespace simulation_grid

#endif
<|endoftext|>