<commit_before>//---------------------------------------------------------
// Copyright 2015 Ontario Institute for Cancer Research
// Written by Matei David (matei@cs.toronto.edu)
//---------------------------------------------------------

// Reference:
// http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c

#ifndef __ZSTR_HPP
#define __ZSTR_HPP

#include <cassert>
#include <fstream>
#include <sstream>
#include <zlib.h>
#include "strict_fstream.hpp"

namespace zstr
{

/// Exception class thrown by failed zlib operations.
class Exception
    : public std::exception
{
public:
    Exception(z_stream * zstrm_p, int ret)
        : _msg("zlib: ")
    {
        switch (ret)
        {
        case Z_STREAM_ERROR:
            _msg += "Z_STREAM_ERROR: ";
            break;
        case Z_DATA_ERROR:
            _msg += "Z_DATA_ERROR: ";
            break;
        case Z_MEM_ERROR:
            _msg += "Z_MEM_ERROR: ";
            break;
        case Z_VERSION_ERROR:
            _msg += "Z_VERSION_ERROR: ";
            break;
        case Z_BUF_ERROR:
            _msg += "Z_BUF_ERROR: ";
            break;
        default:
            std::ostringstream oss;
            oss << ret;
            _msg += "[" + oss.str() + "]: ";
            break;
        }
        _msg += zstrm_p->msg;
    }
    Exception(const std::string msg) : _msg(msg) {}
    const char * what() const noexcept { return _msg.c_str(); }
private:
    std::string _msg;
}; // class Exception

namespace detail
{

class z_stream_wrapper
    : public z_stream
{
public:
    z_stream_wrapper(bool _is_input = true, int _level = Z_DEFAULT_COMPRESSION)
        : is_input(_is_input)
    {
        this->zalloc = Z_NULL;
        this->zfree = Z_NULL;
        this->opaque = Z_NULL;
        int ret;
        if (is_input)
        {
            this->avail_in = 0;
            this->next_in = Z_NULL;
            ret = inflateInit2(this, 15+32);
        }
        else
        {
            ret = deflateInit2(this, _level, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
        }
        if (ret != Z_OK) throw Exception(this, ret);
    }
    ~z_stream_wrapper()
    {
        if (is_input)
        {
            inflateEnd(this);
        }
        else
        {
            deflateEnd(this);
        }
    }
private:
    bool is_input;
}; // class z_stream_wrapper

} // namespace detail

class istreambuf
    : public std::streambuf
{
public:
    istreambuf(std::streambuf * _sbuf_p,
               std::size_t _buff_size = default_buff_size, bool _auto_detect = true)
        : sbuf_p(_sbuf_p),
          zstrm_p(nullptr),
          buff_size(_buff_size),
          auto_detect(_auto_detect),
          auto_detect_run(false),
          is_text(false)
    {
        assert(sbuf_p);
        in_buff = new char [buff_size];
        in_buff_start = in_buff;
        in_buff_end = in_buff;
        out_buff = new char [buff_size];
        setg(out_buff, out_buff, out_buff);
    }

    istreambuf(const istreambuf &) = delete;
    istreambuf(istreambuf &&) = default;
    istreambuf & operator = (const istreambuf &) = delete;
    istreambuf & operator = (istreambuf &&) = default;

    virtual ~istreambuf()
    {
        delete [] in_buff;
        delete [] out_buff;
        if (zstrm_p) delete zstrm_p;
    }

    virtual std::streambuf::int_type underflow()
    {
        if (this->gptr() == this->egptr())
        {
            // pointers for free region in output buffer
            char * out_buff_free_start = out_buff;
            do
            {
                // read more input if none available
                if (in_buff_start == in_buff_end)
                {
                    // empty input buffer: refill from the start
                    in_buff_start = in_buff;
                    std::streamsize sz = sbuf_p->sgetn(in_buff, buff_size);
                    in_buff_end = in_buff + sz;
                    if (in_buff_end == in_buff_start) break; // end of input
                }
                // auto detect if the stream contains text or deflate data
                if (auto_detect && ! auto_detect_run)
                {
                    auto_detect_run = true;
                    unsigned char b0 = *reinterpret_cast< unsigned char * >(in_buff_start);
                    unsigned char b1 = *reinterpret_cast< unsigned char * >(in_buff_start + 1);
                    // Ref:
                    // http://en.wikipedia.org/wiki/Gzip
                    // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
                    is_text = ! (in_buff_start + 2 <= in_buff_end
                                 && ((b0 == 0x1F && b1 == 0x8B)         // gzip header
                                     || (b0 == 0x78 && (b1 == 0x01      // zlib header
                                                        || b1 == 0x9C
                                                        || b1 == 0xDA))));
                }
                if (is_text)
                {
                    // simply swap in_buff and out_buff, and adjust pointers
                    assert(in_buff_start == in_buff);
                    std::swap(in_buff, out_buff);
                    out_buff_free_start = in_buff_end;
                    in_buff_start = in_buff;
                    in_buff_end = in_buff;
                }
                else
                {
                    // run inflate() on input
                    if (! zstrm_p) zstrm_p = new detail::z_stream_wrapper(true);
                    zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(in_buff_start);
                    zstrm_p->avail_in = in_buff_end - in_buff_start;
                    zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff_free_start);
                    zstrm_p->avail_out = (out_buff + buff_size) - out_buff_free_start;
                    int ret = inflate(zstrm_p, Z_NO_FLUSH);
                    // process return code
                    if (ret != Z_OK && ret != Z_STREAM_END) throw Exception(zstrm_p, ret);
                    // update in&out pointers following inflate()
                    in_buff_start = reinterpret_cast< decltype(in_buff_start) >(zstrm_p->next_in);
                    in_buff_end = in_buff_start + zstrm_p->avail_in;
                    out_buff_free_start = reinterpret_cast< decltype(out_buff_free_start) >(zstrm_p->next_out);
                    assert(out_buff_free_start + zstrm_p->avail_out == out_buff + buff_size);
                    // if stream ended, deallocate inflator
                    if (ret == Z_STREAM_END)
                    {
                        delete zstrm_p;
                        zstrm_p = nullptr;
                    }
                }
            } while (out_buff_free_start == out_buff);
            // 2 exit conditions:
            // - end of input: there might or might not be output available
            // - out_buff_free_start != out_buff: output available
            this->setg(out_buff, out_buff, out_buff_free_start);
        }
        return this->gptr() == this->egptr()
            ? traits_type::eof()
            : traits_type::to_int_type(*this->gptr());
    }
private:
    std::streambuf * sbuf_p;
    char * in_buff;
    char * in_buff_start;
    char * in_buff_end;
    char * out_buff;
    detail::z_stream_wrapper * zstrm_p;
    std::size_t buff_size;
    bool auto_detect;
    bool auto_detect_run;
    bool is_text;

    static const std::size_t default_buff_size = (std::size_t)1 << 20;
}; // class istreambuf

class ostreambuf
    : public std::streambuf
{
public:
    ostreambuf(std::streambuf * _sbuf_p,
               std::size_t _buff_size = default_buff_size, int _level = Z_DEFAULT_COMPRESSION)
        : sbuf_p(_sbuf_p),
          zstrm_p(new detail::z_stream_wrapper(false, _level)),
          buff_size(_buff_size)
    {
        assert(sbuf_p);
        in_buff = new char [buff_size];
        out_buff = new char [buff_size];
        setp(in_buff, in_buff + buff_size);
    }

    ostreambuf(const ostreambuf &) = delete;
    ostreambuf(ostreambuf &&) = default;
    ostreambuf & operator = (const ostreambuf &) = delete;
    ostreambuf & operator = (ostreambuf &&) = default;

    int deflate_loop(int flush)
    {
        while (true)
        {
            zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff);
            zstrm_p->avail_out = buff_size;
            int ret = deflate(zstrm_p, flush);
            if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) throw Exception(zstrm_p, ret);
            std::streamsize sz = sbuf_p->sputn(out_buff, reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff);
            if (sz != reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff)
            {
                // there was an error in the sink stream
                return -1;
            }
            if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0)
            {
                break;
            }
        }
        return 0;
    }

    virtual ~ostreambuf()
    {
        // flush the zlib stream
        //
        // NOTE: Errors here (sync() return value not 0) are ignored, because we
        // cannot throw in a destructor. This mirrors the behaviour of
        // std::basic_filebuf::~basic_filebuf(). To see an exception on error,
        // close the ofstream with an explicit call to close(), and do not rely
        // on the implicit call in the destructor.
        //
        sync();
        delete [] in_buff;
        delete [] out_buff;
        delete zstrm_p;
    }
    virtual std::streambuf::int_type overflow(std::streambuf::int_type c = traits_type::eof())
    {
        zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(pbase());
        zstrm_p->avail_in = pptr() - pbase();
        while (zstrm_p->avail_in > 0)
        {
            int r = deflate_loop(Z_NO_FLUSH);
            if (r != 0)
            {
                setp(nullptr, nullptr);
                return traits_type::eof();
            }
        }
        setp(in_buff, in_buff + buff_size);
        return traits_type::eq_int_type(c, traits_type::eof()) ? traits_type::eof() : sputc(c);
    }
    virtual int sync()
    {
        // first, call overflow to clear in_buff
        overflow();
        if (! pptr()) return -1;
        // then, call deflate asking to finish the zlib stream
        zstrm_p->next_in = nullptr;
        zstrm_p->avail_in = 0;
        if (deflate_loop(Z_FINISH) != 0) return -1;
        deflateReset(zstrm_p);
        return 0;
    }
private:
    std::streambuf * sbuf_p;
    char * in_buff;
    char * out_buff;
    detail::z_stream_wrapper * zstrm_p;
    std::size_t buff_size;

    static const std::size_t default_buff_size = (std::size_t)1 << 20;
}; // class ostreambuf

class istream
    : public std::istream
{
public:
    istream(std::istream & is)
        : std::istream(new istreambuf(is.rdbuf()))
    {
        exceptions(std::ios_base::badbit);
    }
    explicit istream(std::streambuf * sbuf_p)
        : std::istream(new istreambuf(sbuf_p))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~istream()
    {
        delete rdbuf();
    }
}; // class istream

class ostream
    : public std::ostream
{
public:
    ostream(std::ostream & os)
        : std::ostream(new ostreambuf(os.rdbuf()))
    {
        exceptions(std::ios_base::badbit);
    }
    explicit ostream(std::streambuf * sbuf_p)
        : std::ostream(new ostreambuf(sbuf_p))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~ostream()
    {
        delete rdbuf();
    }
}; // class ostream

namespace detail
{

template < typename FStream_Type >
struct strict_fstream_holder
{
    strict_fstream_holder(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
        : _fs(filename, mode)
    {}
    FStream_Type _fs;
}; // class strict_fstream_holder

} // namespace detail

class ifstream
    : private detail::strict_fstream_holder< strict_fstream::ifstream >,
      public std::istream
{
public:
    explicit ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
        : detail::strict_fstream_holder< strict_fstream::ifstream >(filename, mode),
          std::istream(new istreambuf(_fs.rdbuf()))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~ifstream()
    {
        if (rdbuf()) delete rdbuf();
    }
}; // class ifstream

class ofstream
    : private detail::strict_fstream_holder< strict_fstream::ofstream >,
      public std::ostream
{
public:
    explicit ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
        : detail::strict_fstream_holder< strict_fstream::ofstream >(filename, mode | std::ios_base::binary),
          std::ostream(new ostreambuf(_fs.rdbuf()))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~ofstream()
    {
        if (rdbuf()) delete rdbuf();
    }
}; // class ofstream

} // namespace zstr

#endif
<commit_msg>moved buff size and compression level up to public ostream::zstr interface<commit_after>//---------------------------------------------------------
// Copyright 2015 Ontario Institute for Cancer Research
// Written by Matei David (matei@cs.toronto.edu)
//---------------------------------------------------------

// Reference:
// http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c

#ifndef __ZSTR_HPP
#define __ZSTR_HPP

#include <cassert>
#include <fstream>
#include <sstream>
#include <zlib.h>
#include "strict_fstream.hpp"

namespace zstr
{

/// Exception class thrown by failed zlib operations.
class Exception
    : public std::exception
{
public:
    Exception(z_stream * zstrm_p, int ret)
        : _msg("zlib: ")
    {
        switch (ret)
        {
        case Z_STREAM_ERROR:
            _msg += "Z_STREAM_ERROR: ";
            break;
        case Z_DATA_ERROR:
            _msg += "Z_DATA_ERROR: ";
            break;
        case Z_MEM_ERROR:
            _msg += "Z_MEM_ERROR: ";
            break;
        case Z_VERSION_ERROR:
            _msg += "Z_VERSION_ERROR: ";
            break;
        case Z_BUF_ERROR:
            _msg += "Z_BUF_ERROR: ";
            break;
        default:
            std::ostringstream oss;
            oss << ret;
            _msg += "[" + oss.str() + "]: ";
            break;
        }
        _msg += zstrm_p->msg;
    }
    Exception(const std::string msg) : _msg(msg) {}
    const char * what() const noexcept { return _msg.c_str(); }
private:
    std::string _msg;
}; // class Exception

namespace detail
{

class z_stream_wrapper
    : public z_stream
{
public:
    z_stream_wrapper(bool _is_input = true, int _level = Z_DEFAULT_COMPRESSION)
        : is_input(_is_input)
    {
        this->zalloc = Z_NULL;
        this->zfree = Z_NULL;
        this->opaque = Z_NULL;
        int ret;
        if (is_input)
        {
            this->avail_in = 0;
            this->next_in = Z_NULL;
            ret = inflateInit2(this, 15+32);
        }
        else
        {
            ret = deflateInit2(this, _level, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
        }
        if (ret != Z_OK) throw Exception(this, ret);
    }
    ~z_stream_wrapper()
    {
        if (is_input)
        {
            inflateEnd(this);
        }
        else
        {
            deflateEnd(this);
        }
    }
private:
    bool is_input;
}; // class z_stream_wrapper

} // namespace detail

class istreambuf
    : public std::streambuf
{
public:
    istreambuf(std::streambuf * _sbuf_p,
               std::size_t _buff_size = default_buff_size, bool _auto_detect = true)
        : sbuf_p(_sbuf_p),
          zstrm_p(nullptr),
          buff_size(_buff_size),
          auto_detect(_auto_detect),
          auto_detect_run(false),
          is_text(false)
    {
        assert(sbuf_p);
        in_buff = new char [buff_size];
        in_buff_start = in_buff;
        in_buff_end = in_buff;
        out_buff = new char [buff_size];
        setg(out_buff, out_buff, out_buff);
    }

    istreambuf(const istreambuf &) = delete;
    istreambuf(istreambuf &&) = default;
    istreambuf & operator = (const istreambuf &) = delete;
    istreambuf & operator = (istreambuf &&) = default;

    virtual ~istreambuf()
    {
        delete [] in_buff;
        delete [] out_buff;
        if (zstrm_p) delete zstrm_p;
    }

    virtual std::streambuf::int_type underflow()
    {
        if (this->gptr() == this->egptr())
        {
            // pointers for free region in output buffer
            char * out_buff_free_start = out_buff;
            do
            {
                // read more input if none available
                if (in_buff_start == in_buff_end)
                {
                    // empty input buffer: refill from the start
                    in_buff_start = in_buff;
                    std::streamsize sz = sbuf_p->sgetn(in_buff, buff_size);
                    in_buff_end = in_buff + sz;
                    if (in_buff_end == in_buff_start) break; // end of input
                }
                // auto detect if the stream contains text or deflate data
                if (auto_detect && ! auto_detect_run)
                {
                    auto_detect_run = true;
                    unsigned char b0 = *reinterpret_cast< unsigned char * >(in_buff_start);
                    unsigned char b1 = *reinterpret_cast< unsigned char * >(in_buff_start + 1);
                    // Ref:
                    // http://en.wikipedia.org/wiki/Gzip
                    // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
                    is_text = ! (in_buff_start + 2 <= in_buff_end
                                 && ((b0 == 0x1F && b1 == 0x8B)         // gzip header
                                     || (b0 == 0x78 && (b1 == 0x01      // zlib header
                                                        || b1 == 0x9C
                                                        || b1 == 0xDA))));
                }
                if (is_text)
                {
                    // simply swap in_buff and out_buff, and adjust pointers
                    assert(in_buff_start == in_buff);
                    std::swap(in_buff, out_buff);
                    out_buff_free_start = in_buff_end;
                    in_buff_start = in_buff;
                    in_buff_end = in_buff;
                }
                else
                {
                    // run inflate() on input
                    if (! zstrm_p) zstrm_p = new detail::z_stream_wrapper(true);
                    zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(in_buff_start);
                    zstrm_p->avail_in = in_buff_end - in_buff_start;
                    zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff_free_start);
                    zstrm_p->avail_out = (out_buff + buff_size) - out_buff_free_start;
                    int ret = inflate(zstrm_p, Z_NO_FLUSH);
                    // process return code
                    if (ret != Z_OK && ret != Z_STREAM_END) throw Exception(zstrm_p, ret);
                    // update in&out pointers following inflate()
                    in_buff_start = reinterpret_cast< decltype(in_buff_start) >(zstrm_p->next_in);
                    in_buff_end = in_buff_start + zstrm_p->avail_in;
                    out_buff_free_start = reinterpret_cast< decltype(out_buff_free_start) >(zstrm_p->next_out);
                    assert(out_buff_free_start + zstrm_p->avail_out == out_buff + buff_size);
                    // if stream ended, deallocate inflator
                    if (ret == Z_STREAM_END)
                    {
                        delete zstrm_p;
                        zstrm_p = nullptr;
                    }
                }
            } while (out_buff_free_start == out_buff);
            // 2 exit conditions:
            // - end of input: there might or might not be output available
            // - out_buff_free_start != out_buff: output available
            this->setg(out_buff, out_buff, out_buff_free_start);
        }
        return this->gptr() == this->egptr()
            ? traits_type::eof()
            : traits_type::to_int_type(*this->gptr());
    }
    static const std::size_t default_buff_size = (std::size_t)1 << 20;
private:
    std::streambuf * sbuf_p;
    char * in_buff;
    char * in_buff_start;
    char * in_buff_end;
    char * out_buff;
    detail::z_stream_wrapper * zstrm_p;
    std::size_t buff_size;
    bool auto_detect;
    bool auto_detect_run;
    bool is_text;

}; // class istreambuf

class ostreambuf
    : public std::streambuf
{
public:
    ostreambuf(std::streambuf * _sbuf_p,
               std::size_t _buff_size = default_buff_size, int _level = Z_DEFAULT_COMPRESSION)
        : sbuf_p(_sbuf_p),
          zstrm_p(new detail::z_stream_wrapper(false, _level)),
          buff_size(_buff_size)
    {
        assert(sbuf_p);
        in_buff = new char [buff_size];
        out_buff = new char [buff_size];
        setp(in_buff, in_buff + buff_size);
    }

    ostreambuf(const ostreambuf &) = delete;
    ostreambuf(ostreambuf &&) = default;
    ostreambuf & operator = (const ostreambuf &) = delete;
    ostreambuf & operator = (ostreambuf &&) = default;

    int deflate_loop(int flush)
    {
        while (true)
        {
            zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff);
            zstrm_p->avail_out = buff_size;
            int ret = deflate(zstrm_p, flush);
            if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) throw Exception(zstrm_p, ret);
            std::streamsize sz = sbuf_p->sputn(out_buff, reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff);
            if (sz != reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff)
            {
                // there was an error in the sink stream
                return -1;
            }
            if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0)
            {
                break;
            }
        }
        return 0;
    }

    virtual ~ostreambuf()
    {
        // flush the zlib stream
        //
        // NOTE: Errors here (sync() return value not 0) are ignored, because we
        // cannot throw in a destructor. This mirrors the behaviour of
        // std::basic_filebuf::~basic_filebuf(). To see an exception on error,
        // close the ofstream with an explicit call to close(), and do not rely
        // on the implicit call in the destructor.
        //
        sync();
        delete [] in_buff;
        delete [] out_buff;
        delete zstrm_p;
    }
    virtual std::streambuf::int_type overflow(std::streambuf::int_type c = traits_type::eof())
    {
        zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(pbase());
        zstrm_p->avail_in = pptr() - pbase();
        while (zstrm_p->avail_in > 0)
        {
            int r = deflate_loop(Z_NO_FLUSH);
            if (r != 0)
            {
                setp(nullptr, nullptr);
                return traits_type::eof();
            }
        }
        setp(in_buff, in_buff + buff_size);
        return traits_type::eq_int_type(c, traits_type::eof()) ? traits_type::eof() : sputc(c);
    }
    virtual int sync()
    {
        // first, call overflow to clear in_buff
        overflow();
        if (! pptr()) return -1;
        // then, call deflate asking to finish the zlib stream
        zstrm_p->next_in = nullptr;
        zstrm_p->avail_in = 0;
        if (deflate_loop(Z_FINISH) != 0) return -1;
        deflateReset(zstrm_p);
        return 0;
    }
    static const std::size_t default_buff_size = (std::size_t)1 << 20;
private:
    std::streambuf * sbuf_p;
    char * in_buff;
    char * out_buff;
    detail::z_stream_wrapper * zstrm_p;
    std::size_t buff_size;

}; // class ostreambuf

class istream
    : public std::istream
{
public:
    istream(std::istream & is)
        : std::istream(new istreambuf(is.rdbuf()))
    {
        exceptions(std::ios_base::badbit);
    }
    explicit istream(std::streambuf * sbuf_p)
        : std::istream(new istreambuf(sbuf_p))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~istream()
    {
        delete rdbuf();
    }
}; // class istream

class ostream
    : public std::ostream
{
public:
    ostream(std::ostream & os)
        : std::ostream(new ostreambuf(os.rdbuf()))
    {
        exceptions(std::ios_base::badbit);
    }
    explicit ostream(std::streambuf * sbuf_p)
        : std::ostream(new ostreambuf(sbuf_p))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~ostream()
    {
        delete rdbuf();
    }
}; // class ostream

namespace detail
{

template < typename FStream_Type >
struct strict_fstream_holder
{
    strict_fstream_holder(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
        : _fs(filename, mode)
    {}
    FStream_Type _fs;
}; // class strict_fstream_holder

} // namespace detail

class ifstream
    : private detail::strict_fstream_holder< strict_fstream::ifstream >,
      public std::istream
{
public:
    explicit ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in, size_t buff_size = istreambuf::default_buff_size)
        : detail::strict_fstream_holder< strict_fstream::ifstream >(filename, mode),
          std::istream(new istreambuf(_fs.rdbuf(), buff_size))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~ifstream()
    {
        if (_fs.is_open()) close();
        if (rdbuf()) delete rdbuf();
    }
    streampos zstr_tellg()
    {
        return _fs.tellg();
    }
    virtual void close()
    {
        _fs.close();
    }
}; // class ifstream

class ofstream
    : private detail::strict_fstream_holder< strict_fstream::ofstream >,
      public std::ostream
{
public:
    explicit ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out, int compress_level = Z_DEFAULT_COMPRESSION, size_t buff_size = ostreambuf::default_buff_size)
        : detail::strict_fstream_holder< strict_fstream::ofstream >(filename, mode | std::ios_base::binary),
          std::ostream(new ostreambuf(_fs.rdbuf(), buff_size, compress_level))
    {
        exceptions(std::ios_base::badbit);
    }
    virtual ~ofstream()
    {
        if (_fs.is_open()) close();
        if (rdbuf()) delete rdbuf();
    }
    virtual void close()
    {
        std::ostream::flush();
        _fs.close();
    }
}; // class ofstream

} // namespace zstr

#endif
<|endoftext|>


<commit_before>//snippet-sourcedescription:[put_object.cpp demonstrates how to asynchronously put a file into an Amazon S3 bucket.]
//snippet-service:[s3]
//snippet-keyword:[Amazon S3]
//snippet-keyword:[C++]
//snippet-keyword:[Code Sample]
//snippet-sourcetype:[snippet]
//snippet-sourcedate:[2019-04-19]
//snippet-sourceauthor:[AWS]

/*
   Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

   This file is licensed under the Apache License, Version 2.0 (the "License").
   You may not use this file except in compliance with the License. A copy of
   the License is located at

    http://aws.amazon.com/apache2.0/

   This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied. See the License for the
   specific language governing permissions and limitations under the License.
*/

// snippet-start:[s3.cpp.put_object_async.inc]
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/PutObjectRequest.h>
#include <chrono>
#include <condition_variable>
#include <fstream>
#include <iostream>
#include <mutex>
#include <sys/stat.h>
#include <thread>
// snippet-end:[s3.cpp.put_object_async.inc]

/**
 * Check if file exists
 *
 * Note: If using C++17, can use std::filesystem::exists()
 */
inline bool file_exists(const std::string& name)
{
    struct stat buffer;
    return (stat(name.c_str(), &buffer) == 0);
}

/**
 * Function called when PutObjectAsync() finishes
 *
 * The thread that started the async operation is waiting for notification
 * that the operation has finished. A std::condition_variable is used to
 * communicate between the two threads.
*/
// snippet-start:[s3.cpp.put_object_async.mutex_vars]
std::mutex upload_mutex;
std::condition_variable upload_variable;
// snippet-end:[s3.cpp.put_object_async.mutex_vars]

// snippet-start:[s3.cpp.put_object_async_finished.code]
void put_object_async_finished(const Aws::S3::S3Client* client,
    const Aws::S3::Model::PutObjectRequest& request,
    const Aws::S3::Model::PutObjectOutcome& outcome,
    const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context)
{
    // Output operation status
    if (outcome.IsSuccess()) {
        std::cout << "put_object_async_finished: Finished uploading "
            << context->GetUUID() << std::endl;
    }
    else {
        auto error = outcome.GetError();
        std::cout << "ERROR: " << error.GetExceptionName() << ": "
            << error.GetMessage() << std::endl;
    }

    // Notify waiting function
    upload_variable.notify_one();
}
// snippet-end:[s3.cpp.put_object_async_finished.code]

/**
 * Asynchronously put an object into an Amazon S3 bucket
 */
// snippet-start:[s3.cpp.put_object_async.code]
bool put_s3_object_async(const Aws::S3::S3Client& s3_client,
    const Aws::String& s3_bucket_name,
    const Aws::String& s3_object_name,
    const std::string& file_name)
{
    // Verify file_name exists
    if (!file_exists(file_name)) {
        std::cout << "ERROR: NoSuchFile: The specified file does not exist"
            << std::endl;
        return false;
    }

    // Set up request
    Aws::S3::Model::PutObjectRequest object_request;

    object_request.SetBucket(s3_bucket_name);
    object_request.SetKey(s3_object_name);
    const std::shared_ptr<Aws::IOStream> input_data =
        Aws::MakeShared<Aws::FStream>("SampleAllocationTag",
            file_name.c_str(),
            std::ios_base::in | std::ios_base::binary);
    object_request.SetBody(input_data);
    auto context =
        Aws::MakeShared<Aws::Client::AsyncCallerContext>("PutObjectAllocationTag");
    context->SetUUID(s3_object_name);

    // Put the object asynchronously
    s3_client.PutObjectAsync(object_request,
                             put_object_async_finished,
                             context);
    return true;
    // snippet-end:[s3.cpp.put_object_async.code]
}

/**
 * Exercise put_s3_object_async()
 */
int main(int argc, char** argv)
{

    Aws::SDKOptions options;
    Aws::InitAPI(options);
    {
        // Assign these values before running the program
        const Aws::String bucket_name = "BUCKET_NAME";
        const Aws::String object_name = "OBJECT_NAME";
        const std::string file_name = "FILE_NAME_TO_UPLOAD";
        const Aws::String region = "";      // Optional

        // If a region is specified, use it
        Aws::Client::ClientConfiguration clientConfig;
        if (!region.empty())
            clientConfig.region = region;

        // snippet-start:[s3.cpp.put_object_async.invoke.code]
        // NOTE: The S3Client object that starts the async operation must
        // continue to exist until the async operation completes.
        Aws::S3::S3Client s3Client(clientConfig);

        // Put the file into the S3 bucket asynchronously
        std::unique_lock<std::mutex> lock(upload_mutex);
        if (put_s3_object_async(s3Client,
                                bucket_name,
                                object_name,
                                file_name)) {
            // While the upload is in progress, we can perform other tasks.
            // For this example, we just wait for the upload to finish.
            std::cout << "main: Waiting for file upload to complete..."
                << std::endl;
            upload_variable.wait(lock);

            // The upload has finished. The S3Client object can be cleaned up
            // now. We can also terminate the program if we wish.
            std::cout << "main: File upload completed" << std::endl;
        }
        // snippet-end:[s3.cpp.put_object_async.invoke.code]
    }
    Aws::ShutdownAPI(options);
}
<commit_msg>Add code comment<commit_after>//snippet-sourcedescription:[put_object.cpp demonstrates how to asynchronously put a file into an Amazon S3 bucket.]
//snippet-service:[s3]
//snippet-keyword:[Amazon S3]
//snippet-keyword:[C++]
//snippet-keyword:[Code Sample]
//snippet-sourcetype:[snippet]
//snippet-sourcedate:[2019-04-19]
//snippet-sourceauthor:[AWS]

/*
   Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

   This file is licensed under the Apache License, Version 2.0 (the "License").
   You may not use this file except in compliance with the License. A copy of
   the License is located at

    http://aws.amazon.com/apache2.0/

   This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied. See the License for the
   specific language governing permissions and limitations under the License.
*/

// snippet-start:[s3.cpp.put_object_async.inc]
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/PutObjectRequest.h>
#include <chrono>
#include <condition_variable>
#include <fstream>
#include <iostream>
#include <mutex>
#include <sys/stat.h>
#include <thread>
// snippet-end:[s3.cpp.put_object_async.inc]

/**
 * Check if file exists
 *
 * Note: If using C++17, can use std::filesystem::exists()
 */
inline bool file_exists(const std::string& name)
{
    struct stat buffer;
    return (stat(name.c_str(), &buffer) == 0);
}

/**
 * Function called when PutObjectAsync() finishes
 *
 * The thread that started the async operation is waiting for notification
 * that the operation has finished. A std::condition_variable is used to
 * communicate between the two threads.
*/
// snippet-start:[s3.cpp.put_object_async.mutex_vars]
std::mutex upload_mutex;
std::condition_variable upload_variable;
// snippet-end:[s3.cpp.put_object_async.mutex_vars]

// snippet-start:[s3.cpp.put_object_async_finished.code]
void put_object_async_finished(const Aws::S3::S3Client* client,
    const Aws::S3::Model::PutObjectRequest& request,
    const Aws::S3::Model::PutObjectOutcome& outcome,
    const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context)
{
    // Output operation status
    if (outcome.IsSuccess()) {
        std::cout << "put_object_async_finished: Finished uploading "
            << context->GetUUID() << std::endl;
    }
    else {
        auto error = outcome.GetError();
        std::cout << "ERROR: " << error.GetExceptionName() << ": "
            << error.GetMessage() << std::endl;
    }

    // Notify waiting function
    upload_variable.notify_one();
}
// snippet-end:[s3.cpp.put_object_async_finished.code]

/**
 * Asynchronously put an object into an Amazon S3 bucket
 */
// snippet-start:[s3.cpp.put_object_async.code]
bool put_s3_object_async(const Aws::S3::S3Client& s3_client,
    const Aws::String& s3_bucket_name,
    const Aws::String& s3_object_name,
    const std::string& file_name)
{
    // Verify file_name exists
    if (!file_exists(file_name)) {
        std::cout << "ERROR: NoSuchFile: The specified file does not exist"
            << std::endl;
        return false;
    }

    // Set up request
    Aws::S3::Model::PutObjectRequest object_request;

    object_request.SetBucket(s3_bucket_name);
    object_request.SetKey(s3_object_name);
    const std::shared_ptr<Aws::IOStream> input_data =
        Aws::MakeShared<Aws::FStream>("SampleAllocationTag",
            file_name.c_str(),
            std::ios_base::in | std::ios_base::binary);
    object_request.SetBody(input_data);

    // Set up AsyncCallerContext. Pass the S3 object name to the callback.
    auto context =
        Aws::MakeShared<Aws::Client::AsyncCallerContext>("PutObjectAllocationTag");
    context->SetUUID(s3_object_name);

    // Put the object asynchronously
    s3_client.PutObjectAsync(object_request,
                             put_object_async_finished,
                             context);
    return true;
    // snippet-end:[s3.cpp.put_object_async.code]
}

/**
 * Exercise put_s3_object_async()
 */
int main(int argc, char** argv)
{

    Aws::SDKOptions options;
    Aws::InitAPI(options);
    {
        // Assign these values before running the program
        const Aws::String bucket_name = "BUCKET_NAME";
        const Aws::String object_name = "OBJECT_NAME";
        const std::string file_name = "FILE_NAME_TO_UPLOAD";
        const Aws::String region = "";      // Optional

        // If a region is specified, use it
        Aws::Client::ClientConfiguration clientConfig;
        if (!region.empty())
            clientConfig.region = region;

        // snippet-start:[s3.cpp.put_object_async.invoke.code]
        // NOTE: The S3Client object that starts the async operation must
        // continue to exist until the async operation completes.
        Aws::S3::S3Client s3Client(clientConfig);

        // Put the file into the S3 bucket asynchronously
        std::unique_lock<std::mutex> lock(upload_mutex);
        if (put_s3_object_async(s3Client,
                                bucket_name,
                                object_name,
                                file_name)) {
            // While the upload is in progress, we can perform other tasks.
            // For this example, we just wait for the upload to finish.
            std::cout << "main: Waiting for file upload to complete..."
                << std::endl;
            upload_variable.wait(lock);

            // The upload has finished. The S3Client object can be cleaned up
            // now. We can also terminate the program if we wish.
            std::cout << "main: File upload completed" << std::endl;
        }
        // snippet-end:[s3.cpp.put_object_async.invoke.code]
    }
    Aws::ShutdownAPI(options);
}
<|endoftext|>


<commit_before>#include "uvdisplaywidget.h"
#include "ui_displaywidget.h"

#include <QTableWidget>
#include <QStandardItem>
#include <QPushButton>
#include <QMessageBox>

#include "changesemestredialog.h"
#include "changecreditsdialog.h"
#include "src/uvmanager.hpp"
#include "src/exceptions.hpp"

#define UVM UvManager::getInstance()
#define NBCOLS 4
#define CODE_COL 0
#define DESCR_COL 1
#define CREDS_COL 2
#define OUV_COL 3

UvDisplayWidget::UvDisplayWidget(QWidget *parent) :
    DisplayWidget(parent)
{
    QStringList cols;
    cols<<"Code"<<"Description"<<"Crédits"<<"Ouverture";
    ui->searchOptions->addItems(cols);

    ui->tableWidget->setRowCount(0);
    ui->tableWidget->setColumnCount(NBCOLS);
    ui->tableWidget->setHorizontalHeaderLabels(cols);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

}

UvDisplayWidget::~UvDisplayWidget() {  }

void UvDisplayWidget::add() {}

void UvDisplayWidget::del() {
    QList<QTableWidgetSelectionRange> ranges = ui->tableWidget->selectedRanges();

    if (ranges.length() == 0) {
        QMessageBox error(this);
        error.setText("Aucune ligne sélectionnée");
        error.exec();
        return;
    }

    for(auto it=ranges.begin(); it!=ranges.end(); it++) {
        for(int i=it->bottomRow(); i>=it->topRow(); --i) {
            QString code = ui->tableWidget->itemAt(CODE_COL, i)->text();
            std::cout<<i<<" "<<code.toStdString()<<std::endl;
            try {
                UVM->suppItem(code);
            } catch (const Exception &e) {
                QMessageBox error(this);
                error.setText(e.getinfo());
                error.exec();
                return;
            }
        }
    }

    refresh();
}

void UvDisplayWidget::changed(int row, int column) {
    QString code = ui->tableWidget->item(row, CODE_COL)->text();
    QString value = ui->tableWidget->item(row, column)->text();
    Uv& concerned = UVM->getItem(code);

    switch (column) {
        case DESCR_COL:
            concerned.setDescription(value);
            break;
        default:
            break;
    }
}

void UvDisplayWidget::filter(QString) {
    refresh();
}

void UvDisplayWidget::change(int row, int column) {
    QString code = ui->tableWidget->item(row, CODE_COL)->text();

    switch (column) {
        case OUV_COL: {
            ChangeSemestreDialog* dialog = new ChangeSemestreDialog(this, code);
            if (dialog->exec() == 1) { refresh(); }
            break;
        }

        case CREDS_COL: {
            ChangeCreditsDialog* dialog = new ChangeCreditsDialog(this, code);
            dialog->exec();
            refresh();
            break;
        }
        default:
            break;
    }
}

void UvDisplayWidget::displayItem(const QString& item) {
    QString code, descr, ouv, rec;
    QStringList ouvertures, recs;
    Uv u = UVM->getItem(item);

    std::map<QString, unsigned int> recompenses = u.getRecompenses();

    for(const auto &rec : recompenses) {
        QString cat = rec.first;
        QString creds = QString::number(rec.second);
        QStringList l;
        l << creds << cat;
        recs << l.join(" ");
    }

    code = u.getCode();
    descr = u.getDescription();

    if (u.getOuverturePrintemps()) { ouvertures<<"Printemps"; }
    if (u.getOuvertureAutomne()) { ouvertures<<"Automne"; }

    ouv = ouvertures.join("/");
    rec = recs.join(" et ");

    if (!ui->searchValue->text().isEmpty()) {
        QString crit = ui->searchValue->text();
        unsigned int col = ui->searchOptions->currentIndex();
        switch (col) {
            case CODE_COL:
                if (!code.contains(crit, Qt::CaseInsensitive)) { return; }
                break;

            case CREDS_COL:
                if (!rec.contains(crit, Qt::CaseInsensitive)) { return; }
                break;

            case DESCR_COL:
                if (!descr.contains(crit, Qt::CaseInsensitive)) { return; }
                break;

            case OUV_COL:
                if (!ouv.contains(crit , Qt::CaseInsensitive)) { return; }
                break;

            default:
                break;
        }
    }

    ui->tableWidget->setItem(offset, CODE_COL, new QTableWidgetItem(code));
    ui->tableWidget->setItem(offset, DESCR_COL, new QTableWidgetItem(descr));
    ui->tableWidget->setItem(offset, OUV_COL, new QTableWidgetItem(ouv));
    ui->tableWidget->setItem(offset, CREDS_COL, new QTableWidgetItem(rec));

    offset++;
}

void UvDisplayWidget::refresh() {
    std::vector<Uv> uvs = UVM->iterator();

    ui->tableWidget->clearContents();
    offset = 0;
    ui->tableWidget->setRowCount(uvs.size());
    ui->tableWidget->setColumnCount(NBCOLS);

    for (auto it=uvs.begin(); it!=uvs.end(); it++) {
        displayItem((*it).getCode());
    }
}
<commit_msg>Ajout d’UVs et fixes<commit_after>#include "uvdisplaywidget.h"
#include "ui_displaywidget.h"

#include <QTableWidget>
#include <QStandardItem>
#include <QPushButton>
#include <QMessageBox>

#include "changesemestredialog.h"
#include "changecreditsdialog.h"
#include "src/uvmanager.hpp"
#include "src/exceptions.hpp"
#include "adduvdialog.h"

#include <iostream>

#define UVM UvManager::getInstance()
#define NBCOLS 4
#define CODE_COL 0
#define DESCR_COL 1
#define CREDS_COL 2
#define OUV_COL 3

UvDisplayWidget::UvDisplayWidget(QWidget *parent) :
    DisplayWidget(parent)
{
    QStringList cols;
    cols<<"Code"<<"Description"<<"Crédits"<<"Ouverture";
    ui->searchOptions->addItems(cols);

    ui->tableWidget->setRowCount(0);
    ui->tableWidget->setColumnCount(NBCOLS);
    ui->tableWidget->setHorizontalHeaderLabels(cols);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    ui->modifyButton->setVisible(false);

}

UvDisplayWidget::~UvDisplayWidget() {  }

void UvDisplayWidget::add() {
    AddUVDialog *dialog = new AddUVDialog(this);
    dialog->exec();
    delete dialog;
}

void UvDisplayWidget::del() {
    QList<QTableWidgetSelectionRange> ranges = ui->tableWidget->selectedRanges();

    if (ranges.length() == 0) {
        QMessageBox error(this);
        error.setText("Aucune ligne sélectionnée");
        error.exec();
        return;
    }

    for(auto it=ranges.begin(); it!=ranges.end(); it++) {
        for(int i=it->bottomRow(); i>=it->topRow(); --i) {
            QString code = ui->tableWidget->item(i, CODE_COL)->text();
            std::cout<<i<<" "<<code.toStdString()<<std::endl;
            try {
                UVM->suppItem(code);
            } catch (const Exception &e) {
                QMessageBox error(this);
                error.setText(e.getinfo());
                error.exec();
                return;
            }
        }
    }

    refresh();
}

void UvDisplayWidget::changed(int row, int column) {
    QString code = ui->tableWidget->item(row, CODE_COL)->text();
    QString value = ui->tableWidget->item(row, column)->text();
    Uv& concerned = UVM->getItem(code);

    switch (column) {
        case DESCR_COL:
            concerned.setDescription(value);
            break;
        default:
            break;
    }
}

void UvDisplayWidget::change(int row, int column) {
    QString code = ui->tableWidget->item(row, CODE_COL)->text();

    switch (column) {
        case OUV_COL: {
            ChangeSemestreDialog* dialog = new ChangeSemestreDialog(this, code);
            if (dialog->exec() == 1) { refresh(); }
            delete dialog;
            break;
        }

        case CREDS_COL: {
            ChangeCreditsDialog* dialog = new ChangeCreditsDialog(this, code);
            dialog->exec();
            delete dialog;
            refresh();
            break;
        }
        default:
            break;
    }
}

void UvDisplayWidget::displayItem(const QString& item) {
    QString code, descr, ouv, rec;
    QStringList ouvertures, recs;
    Uv u = UVM->getItem(item);

    std::map<QString, unsigned int> recompenses = u.getRecompenses();

    for(const auto &rec : recompenses) {
        QString cat = rec.first;
        QString creds = QString::number(rec.second);
        QStringList l;
        l << creds << cat;
        recs << l.join(" ");
    }

    code = u.getCode();
    descr = u.getDescription();

    if (u.getOuverturePrintemps()) { ouvertures<<"Printemps"; }
    if (u.getOuvertureAutomne()) { ouvertures<<"Automne"; }

    ouv = ouvertures.join("/");
    rec = recs.join(" et ");

    if (!ui->searchValue->text().isEmpty()) {
        QString crit = ui->searchValue->text();
        unsigned int col = ui->searchOptions->currentIndex();
        switch (col) {
            case CODE_COL:
                if (!code.contains(crit, Qt::CaseInsensitive)) { return; }
                break;

            case CREDS_COL:
                if (!rec.contains(crit, Qt::CaseInsensitive)) { return; }
                break;

            case DESCR_COL:
                if (!descr.contains(crit, Qt::CaseInsensitive)) { return; }
                break;

            case OUV_COL:
                if (!ouv.contains(crit , Qt::CaseInsensitive)) { return; }
                break;

            default:
                break;
        }
    }

    QTableWidgetItem *codeItem = new QTableWidgetItem(code);
    codeItem->setFlags(codeItem->flags() & ~Qt::ItemIsEditable);
    ui->tableWidget->setItem(offset, CODE_COL, codeItem);
    ui->tableWidget->setItem(offset, DESCR_COL, new QTableWidgetItem(descr));
    ui->tableWidget->setItem(offset, OUV_COL, new QTableWidgetItem(ouv));
    ui->tableWidget->setItem(offset, CREDS_COL, new QTableWidgetItem(rec));

    offset++;
}

void UvDisplayWidget::refresh() {
    std::vector<Uv> uvs = UVM->iterator();

    ui->tableWidget->clearContents();
    offset = 0;
    ui->tableWidget->setRowCount(uvs.size());
    ui->tableWidget->setColumnCount(NBCOLS);

    for (auto it=uvs.begin(); it!=uvs.end(); it++) {
        displayItem((*it).getCode());
    }
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "tsunami_user.h"

#include <fclaw2d_include_all.h>

#include <fclaw2d_clawpatch_options.h>
#include <fclaw2d_clawpatch.h>

#include <fc2d_clawpack46_options.h>
#include <fc2d_clawpack46.h>
#include <fc2d_cudaclaw_options.h>

#include <fc2d_cudaclaw.h>
#include <fc2d_cuda_profiler.h>

static
fclaw2d_domain_t* create_domain(sc_MPI_Comm mpicomm,
                                fclaw_options_t* fclaw_opt,
                                user_options_t* user)
{
    /* Mapped, multi-block domain */
    p4est_connectivity_t     *conn = NULL;
    fclaw2d_domain_t         *domain;
    fclaw2d_map_context_t    *cont = NULL, *brick= NULL;

    int mi = fclaw_opt->mi;
    int mj = fclaw_opt->mj;
    int a = fclaw_opt->periodic_x;
    int b = fclaw_opt->periodic_y;

    /* Use [ax,bx]x[ay,by] */

    conn = p4est_connectivity_new_brick(mi,mj,a,b);
    brick = fclaw2d_map_new_brick(conn,mi,mj);
    cont = fclaw2d_map_new_nomap_brick(brick);

    domain = fclaw2d_domain_new_conn_map (mpicomm, fclaw_opt->minlevel, conn, cont);
    fclaw2d_domain_list_levels(domain, FCLAW_VERBOSITY_ESSENTIAL);
    fclaw2d_domain_list_neighbors(domain, FCLAW_VERBOSITY_DEBUG);
    return domain;
}

static
void run_program(fclaw2d_global_t* glob)
{
    /* ---------------------------------------------------------------
       Set domain data.
       --------------------------------------------------------------- */
    fclaw2d_domain_data_new(glob->domain);

    /* Set domain dimensions so that we have square grid cells */
    fclaw_options_t *fclaw_opt = fclaw2d_get_options(glob);

    double ax = fclaw_opt->ax;
    double bx = fclaw_opt->bx;
    int mi = fclaw_opt->mi;

    fclaw2d_clawpatch_options_t *clawpatch_opt = fclaw2d_clawpatch_get_options(glob);
    int mx = clawpatch_opt->mx;

    double dx = (bx-ax)/(mi*mx);

    fclaw_opt->by = mx*dx;   // To get square mesh cells for pseudo 1d problem

    /* Initialize virtual tables for solvers */
    if(user_opt->cuda)
    {
        fc2d_cudaclaw_options_t *clawopt = fc2d_cudaclaw_get_options(glob);

        fc2d_cudaclaw_initialize_GPUs(glob);

        /* this has to be done after GPUs have been initialized */
        cudaclaw_set_method_parameters(clawopt->order, clawopt->mthlim, clawopt->mwaves);
        fc2d_cudaclaw_solver_initialize();
    }
    else
    {
        if (user_opt->claw_version == 4)
        {
            fc2d_clawpack46_solver_initialize();
        }
        else if (user_opt->claw_version == 5)
        {
            fc2d_clawpack5_solver_initialize();
        }
    }

    /* Initialize virtual table for ForestClaw */
    fclaw2d_vtables_initialize(glob);

    fc2d_clawpack46_solver_initialize();

    tsunami_link_solvers(glob);

    /* ---------------------------------------------------------------
       Run
       --------------------------------------------------------------- */

    if (user_opt->cuda == 1)
    {
        PROFILE_CUDA_GROUP("Allocate GPU and GPU buffers",1);
        fc2d_cudaclaw_allocate_buffers(glob);
    }

    fclaw2d_initialize(glob);
    fclaw2d_run(glob);

    if (user_opt->cuda == 1)
    {
        PROFILE_CUDA_GROUP("De-allocate GPU and GPU buffers",1);
        fc2d_cudaclaw_deallocate_buffers(glob);
    }

    fclaw2d_finalize(glob);
}

int
main (int argc, char **argv)
{
    fclaw_app_t *app;
    int first_arg;
    fclaw_exit_type_t vexit;

    /* Options */
    sc_options_t                *options;
    user_options_t              *user_opt;
    fclaw_options_t             *fclaw_opt;
    fclaw2d_clawpatch_options_t *clawpatch_opt;
    fc2d_clawpack46_options_t   *claw46_opt;
    fc2d_cudaclaw_options_t     *cuclaw5_opt;

    fclaw2d_global_t            *glob;
    fclaw2d_domain_t            *domain;
    sc_MPI_Comm mpicomm;

    int retval;

    /* Initialize application */
    app = fclaw_app_new (&argc, &argv, NULL);

    /* Create new options packages */
    fclaw_opt =                   fclaw_options_register(app,"fclaw_options.ini");
    clawpatch_opt =   fclaw2d_clawpatch_options_register(app,"fclaw_options.ini");
    claw46_opt =        fc2d_clawpack46_options_register(app,"fclaw_options.ini");
    cuclaw_opt =         fc2d_cudaclaw_options_register(app,"fclaw_options.ini");
    user_opt =                tsunami_options_register(app,"fclaw_options.ini");

    /* Read configuration file(s) and command line, and process options */
    options = fclaw_app_get_options (app);
    retval = fclaw_options_read_from_file(options);
    vexit =  fclaw_app_options_parse (app, &first_arg,"fclaw_options.ini.used");

    /* Run the program */
    if (!retval & !vexit)
    {
        /* Options have been checked and are valid */

        mpicomm = fclaw_app_get_mpi_size_rank (app, NULL, NULL);
        domain = create_domain(mpicomm, fclaw_opt,user_opt);

        /* Create global structure which stores the domain, timers, etc */
        glob = fclaw2d_global_new();
        fclaw2d_global_store_domain(glob, domain);

        /* Store option packages in glob */
        fclaw2d_options_store           (glob, fclaw_opt);
        fclaw2d_clawpatch_options_store (glob, clawpatch_opt);
        fc2d_clawpack46_options_store   (glob, claw46_opt);
        fc2d_cudaclaw_options_store     (glob, cuclaw_opt);
        tsunami_options_store           (glob, user_opt);

        run_program(glob);

        fclaw2d_global_destroy(glob);
    }

    fclaw_app_destroy (app);

    return 0;
}

<commit_msg>(tsunami) Fix reference to non-existent cuclaw5<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "tsunami_user.h"

#include <fclaw2d_include_all.h>

#include <fclaw2d_clawpatch_options.h>
#include <fclaw2d_clawpatch.h>

#include <fc2d_clawpack46_options.h>
#include <fc2d_clawpack46.h>
#include <fc2d_cudaclaw_options.h>

#include <fc2d_cudaclaw.h>
#include <fc2d_cuda_profiler.h>

static
fclaw2d_domain_t* create_domain(sc_MPI_Comm mpicomm,
                                fclaw_options_t* fclaw_opt,
                                user_options_t* user)
{
    /* Mapped, multi-block domain */
    p4est_connectivity_t     *conn = NULL;
    fclaw2d_domain_t         *domain;
    fclaw2d_map_context_t    *cont = NULL, *brick= NULL;

    int mi = fclaw_opt->mi;
    int mj = fclaw_opt->mj;
    int a = fclaw_opt->periodic_x;
    int b = fclaw_opt->periodic_y;

    /* Use [ax,bx]x[ay,by] */

    conn = p4est_connectivity_new_brick(mi,mj,a,b);
    brick = fclaw2d_map_new_brick(conn,mi,mj);
    cont = fclaw2d_map_new_nomap_brick(brick);

    domain = fclaw2d_domain_new_conn_map (mpicomm, fclaw_opt->minlevel, conn, cont);
    fclaw2d_domain_list_levels(domain, FCLAW_VERBOSITY_ESSENTIAL);
    fclaw2d_domain_list_neighbors(domain, FCLAW_VERBOSITY_DEBUG);
    return domain;
}

static
void run_program(fclaw2d_global_t* glob)
{
    /* ---------------------------------------------------------------
       Set domain data.
       --------------------------------------------------------------- */
    fclaw2d_domain_data_new(glob->domain);

    /* Set domain dimensions so that we have square grid cells */
    fclaw_options_t *fclaw_opt = fclaw2d_get_options(glob);

    double ax = fclaw_opt->ax;
    double bx = fclaw_opt->bx;
    int mi = fclaw_opt->mi;

    fclaw2d_clawpatch_options_t *clawpatch_opt = fclaw2d_clawpatch_get_options(glob);
    int mx = clawpatch_opt->mx;

    double dx = (bx-ax)/(mi*mx);

    fclaw_opt->by = mx*dx;   // To get square mesh cells for pseudo 1d problem

    /* Initialize virtual tables for solvers */
    if(user_opt->cuda)
    {
        fc2d_cudaclaw_options_t *clawopt = fc2d_cudaclaw_get_options(glob);

        fc2d_cudaclaw_initialize_GPUs(glob);

        /* this has to be done after GPUs have been initialized */
        cudaclaw_set_method_parameters(clawopt->order, clawopt->mthlim, clawopt->mwaves);
        fc2d_cudaclaw_solver_initialize();
    }
    else
    {
        if (user_opt->claw_version == 4)
        {
            fc2d_clawpack46_solver_initialize();
        }
        else if (user_opt->claw_version == 5)
        {
            fc2d_clawpack5_solver_initialize();
        }
    }

    /* Initialize virtual table for ForestClaw */
    fclaw2d_vtables_initialize(glob);

    fc2d_clawpack46_solver_initialize();

    tsunami_link_solvers(glob);

    /* ---------------------------------------------------------------
       Run
       --------------------------------------------------------------- */

    if (user_opt->cuda == 1)
    {
        PROFILE_CUDA_GROUP("Allocate GPU and GPU buffers",1);
        fc2d_cudaclaw_allocate_buffers(glob);
    }

    fclaw2d_initialize(glob);
    fclaw2d_run(glob);

    if (user_opt->cuda == 1)
    {
        PROFILE_CUDA_GROUP("De-allocate GPU and GPU buffers",1);
        fc2d_cudaclaw_deallocate_buffers(glob);
    }

    fclaw2d_finalize(glob);
}

int
main (int argc, char **argv)
{
    fclaw_app_t *app;
    int first_arg;
    fclaw_exit_type_t vexit;

    /* Options */
    sc_options_t                *options;
    user_options_t              *user_opt;
    fclaw_options_t             *fclaw_opt;
    fclaw2d_clawpatch_options_t *clawpatch_opt;
    fc2d_clawpack46_options_t   *claw46_opt;
    fc2d_cudaclaw_options_t     *cuclaw_opt;

    fclaw2d_global_t            *glob;
    fclaw2d_domain_t            *domain;
    sc_MPI_Comm mpicomm;

    int retval;

    /* Initialize application */
    app = fclaw_app_new (&argc, &argv, NULL);

    /* Create new options packages */
    fclaw_opt =                   fclaw_options_register(app,"fclaw_options.ini");
    clawpatch_opt =   fclaw2d_clawpatch_options_register(app,"fclaw_options.ini");
    claw46_opt =        fc2d_clawpack46_options_register(app,"fclaw_options.ini");
    cuclaw_opt =         fc2d_cudaclaw_options_register(app,"fclaw_options.ini");
    user_opt =                tsunami_options_register(app,"fclaw_options.ini");

    /* Read configuration file(s) and command line, and process options */
    options = fclaw_app_get_options (app);
    retval = fclaw_options_read_from_file(options);
    vexit =  fclaw_app_options_parse (app, &first_arg,"fclaw_options.ini.used");

    /* Run the program */
    if (!retval & !vexit)
    {
        /* Options have been checked and are valid */

        mpicomm = fclaw_app_get_mpi_size_rank (app, NULL, NULL);
        domain = create_domain(mpicomm, fclaw_opt,user_opt);

        /* Create global structure which stores the domain, timers, etc */
        glob = fclaw2d_global_new();
        fclaw2d_global_store_domain(glob, domain);

        /* Store option packages in glob */
        fclaw2d_options_store           (glob, fclaw_opt);
        fclaw2d_clawpatch_options_store (glob, clawpatch_opt);
        fc2d_clawpack46_options_store   (glob, claw46_opt);
        fc2d_cudaclaw_options_store     (glob, cuclaw_opt);
        tsunami_options_store           (glob, user_opt);

        run_program(glob);

        fclaw2d_global_destroy(glob);
    }

    fclaw_app_destroy (app);

    return 0;
}

<|endoftext|>


<commit_before>/*
 * jcom.butterlp
 * External for Jamoma: 2nd order Butterworth lowpass filter
 * By Trond Lossius, Copyright  2007
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "Jamoma.h"
#define NUM_INPUTS 1
#define NUM_OUTPUTS 1

// Data Structure for this object
typedef struct _butterlp{
    t_pxobject				x_obj;					// Required by MSP (must be first)
    void					*obex;
	tt_lowpass_butterworth	*myFilter;
    tt_audio_signal			*signal_in[NUM_INPUTS];
    tt_audio_signal			*signal_out[NUM_OUTPUTS];
    float					attr_frequency;			// ATTRIBUTE: filter cutoff frequency
} t_butterlp;

// Prototypes for methods: need a method for each incoming message type:
void *butterlp_new(t_symbol *s, long argc, t_atom *argv);
t_int *butterlp_perform(t_int *w);
void butterlp_dsp(t_butterlp *x, t_signal **sp, short *count);
void butterlp_assist(t_butterlp *x, void *b, long msg, long arg, char *dst);
void butterlp_free(t_butterlp *x);
void butterlp_clear(t_butterlp *x);
t_max_err butterlp_setfrequency(t_butterlp *x, void *attr, long argc, t_atom *argv);

// Globals
t_class		*butterlp_class;					// Required. Global pointing to this class

t_symbol	*ps_symbol;
t_symbol	*ps_long;
t_symbol	*ps_float32;
t_symbol	*ps_dumpout;

/************************************************************************************/
// Main() Function

int main(void)				// main recieves a copy of the Max function macros table
{
	long attrflags = 0;
	t_class *c;
	t_object *attr;

	jamoma_init();
	ps_symbol = gensym("symbol");
	ps_long = gensym("long");
	ps_float32 = gensym("float32");
	ps_dumpout = gensym("dumpout");

	// Define our class
	c = class_new("jcom.butterlp~",(method)butterlp_new, (method)butterlp_free, (short)sizeof(t_butterlp),
		(method)0L, A_GIMME, 0);
	class_obexoffset_set(c, calcoffset(t_butterlp, obex));

	// Make methods accessible for our class:
	class_addmethod(c, (method)butterlp_clear,					"clear", 				0);
	class_addmethod(c, (method)butterlp_dsp, 					"dsp", 					A_CANT, 0);
    class_addmethod(c, (method)butterlp_assist, 				"assist",			 	A_CANT, 0);
    class_addmethod(c, (method)object_obex_dumpout, 			"dumpout", 				A_CANT, 0);
    class_addmethod(c, (method)object_obex_quickref,			"quickref", 			A_CANT, 0);
	class_addmethod(c, (method)butterlp_setfrequency,			"/frequency",			A_GIMME, 0);

	// Add attributes to our class:
	// ATTRIBUTE: frequency
	attr = attr_offset_new("frequency", ps_float32, attrflags,
		(method)0L, (method)butterlp_setfrequency, calcoffset(t_butterlp, attr_frequency));
	class_addattr(c, attr);

	// Setup our class to work with MSP
	class_dspinit(c);

	// Finalize our class
	class_register(CLASS_BOX, c);
	butterlp_class = c;
	return 0;
}

/************************************************************************************/
// Object Life

// Create
void *butterlp_new(t_symbol *s, long argc, t_atom *argv)
{
	t_butterlp *x = (t_butterlp *)object_alloc(butterlp_class);

	if(x){
   		object_obex_store((void *)x, ps_dumpout, (object *)outlet_new(x,NULL));	// dumpout
		dsp_setup((t_pxobject *)x, 2);							// Create object with 2 inlets
	    x->x_obj.z_misc = Z_NO_INPLACE;  						// ESSENTIAL!
		outlet_new((t_object *)x, "signal");					// Create signal outlet

		tt_audio_base::set_global_sr((int)sys_getsr());			// Set Tap.Tools global SR...
		tt_audio_base::set_global_vectorsize(sys_getblksize());	// Set Tap.Tools global vector size...
		x->myFilter = new tt_lowpass_butterworth;				// Tap.Tools Blue Objects

		x->signal_in[0] = new tt_audio_signal;
		x->signal_out[0] = new tt_audio_signal;

		x->attr_frequency = 4000.;								// Defaults

		attr_args_process(x,argc,argv);							// Handle attribute args
	}
	return (x);													// Return the pointer
}

// Destroy
void butterlp_free(t_butterlp *x)
{

	dsp_free((t_pxobject *)x);					// Always call dsp_free first in this routine
	delete x->myFilter;

	delete x->signal_in[0];
	delete x->signal_out[1];
}

/************************************************************************************/
// Methods bound to input/inlets

// Method for Assistance Messages
void butterlp_assist(t_butterlp *x, void *b, long msg, long arg, char *dst)
{
	if(msg==1) 			// Inlet
		strcpy(dst, "(signal) Input, (anything) attributes");
	else if(msg==2){ 	// Outlet
		switch(arg){
			case 0: strcpy(dst, "(signal) output"); break;
			case 1: strcpy(dst, "dumpout"); break;
		}
	}
}

// Clear Message: Reste the filter
void butterlp_clear(t_butterlp *x)
{
	x->myFilter->clear();
}

// ATTRIBUTE: Frequency
t_max_err butterlp_setfrequency(t_butterlp *x, void *attr, long argc, t_atom *argv)
{
	x->attr_frequency = atom_getfloat(argv);
	x->myFilter->set_attr(tt_lowpass_butterworth::k_frequency, x->attr_frequency);

	return MAX_ERR_NONE;
	#pragma unused(attr)
}

// Perform Method: Mono
t_int *butterlp_perform(t_int *w)
{
	t_butterlp *x = (t_butterlp *)(w[1]);
	x->signal_in[0]->set_vector((t_float *)(w[2]));
	x->signal_out[0]->set_vector((t_float *)(w[3]));
	x->signal_in[0]->vectorsize = (int)(w[4]);

	x->myFilter->dsp_vector_calc(x->signal_in[0], x->signal_out[0]);

	return (w+5);
}

// DSP Method
void butterlp_dsp(t_butterlp *x, t_signal **sp, short *count)
{
	x->myFilter->set_sr((int)sp[0]->s_sr);
	x->myFilter->clear();

	dsp_add(butterlp_perform, 4, x, sp[0]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}<commit_msg>using commonsyms instead of our own duplication of them.<commit_after>/*
 * jcom.butterlp
 * External for Jamoma: 2nd order Butterworth lowpass filter
 * By Trond Lossius, Copyright  2007
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "Jamoma.h"
#define NUM_INPUTS 1
#define NUM_OUTPUTS 1

// Data Structure for this object
typedef struct _butterlp{
    t_pxobject				x_obj;					// Required by MSP (must be first)
    void					*obex;
	tt_lowpass_butterworth	*myFilter;
    tt_audio_signal			*signal_in[NUM_INPUTS];
    tt_audio_signal			*signal_out[NUM_OUTPUTS];
    float					attr_frequency;			// ATTRIBUTE: filter cutoff frequency
} t_butterlp;

// Prototypes for methods: need a method for each incoming message type:
void *butterlp_new(t_symbol *s, long argc, t_atom *argv);
t_int *butterlp_perform(t_int *w);
void butterlp_dsp(t_butterlp *x, t_signal **sp, short *count);
void butterlp_assist(t_butterlp *x, void *b, long msg, long arg, char *dst);
void butterlp_free(t_butterlp *x);
void butterlp_clear(t_butterlp *x);
t_max_err butterlp_setfrequency(t_butterlp *x, void *attr, long argc, t_atom *argv);

// Globals
static t_class	*butterlp_class;

/************************************************************************************/
// Main() Function

int main(void)				// main recieves a copy of the Max function macros table
{
	long attrflags = 0;
	t_class *c;
	t_object *attr;

	jamoma_init();

	// Define our class
	c = class_new("jcom.butterlp~",(method)butterlp_new, (method)butterlp_free, (short)sizeof(t_butterlp),
		(method)0L, A_GIMME, 0);
	class_obexoffset_set(c, calcoffset(t_butterlp, obex));

	// Make methods accessible for our class:
	class_addmethod(c, (method)butterlp_clear,					"clear", 				0);
	class_addmethod(c, (method)butterlp_dsp, 					"dsp", 					A_CANT, 0);
    class_addmethod(c, (method)butterlp_assist, 				"assist",			 	A_CANT, 0);
    class_addmethod(c, (method)object_obex_dumpout, 			"dumpout", 				A_CANT, 0);
    class_addmethod(c, (method)object_obex_quickref,			"quickref", 			A_CANT, 0);
	class_addmethod(c, (method)butterlp_setfrequency,			"/frequency",			A_GIMME, 0);

	// Add attributes to our class:
	// ATTRIBUTE: frequency
	attr = attr_offset_new("frequency", _sym_float32, attrflags,
		(method)0L, (method)butterlp_setfrequency, calcoffset(t_butterlp, attr_frequency));
	class_addattr(c, attr);

	// Setup our class to work with MSP
	class_dspinit(c);

	// Finalize our class
	class_register(CLASS_BOX, c);
	butterlp_class = c;
	return 0;
}

/************************************************************************************/
// Object Life

// Create
void *butterlp_new(t_symbol *s, long argc, t_atom *argv)
{
	t_butterlp *x = (t_butterlp *)object_alloc(butterlp_class);

	if(x){
   		object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL));	// dumpout
		dsp_setup((t_pxobject *)x, 2);							// Create object with 2 inlets
	    x->x_obj.z_misc = Z_NO_INPLACE;  						// ESSENTIAL!
		outlet_new((t_object *)x, "signal");					// Create signal outlet

		tt_audio_base::set_global_sr((int)sys_getsr());			// Set Tap.Tools global SR...
		tt_audio_base::set_global_vectorsize(sys_getblksize());	// Set Tap.Tools global vector size...
		x->myFilter = new tt_lowpass_butterworth;				// Tap.Tools Blue Objects

		x->signal_in[0] = new tt_audio_signal;
		x->signal_out[0] = new tt_audio_signal;

		x->attr_frequency = 4000.;								// Defaults

		attr_args_process(x,argc,argv);							// Handle attribute args
	}
	return (x);													// Return the pointer
}

// Destroy
void butterlp_free(t_butterlp *x)
{

	dsp_free((t_pxobject *)x);					// Always call dsp_free first in this routine
	delete x->myFilter;

	delete x->signal_in[0];
	delete x->signal_out[1];
}

/************************************************************************************/
// Methods bound to input/inlets

// Method for Assistance Messages
void butterlp_assist(t_butterlp *x, void *b, long msg, long arg, char *dst)
{
	if(msg==1) 			// Inlet
		strcpy(dst, "(signal) Input, (anything) attributes");
	else if(msg==2){ 	// Outlet
		switch(arg){
			case 0: strcpy(dst, "(signal) output"); break;
			case 1: strcpy(dst, "dumpout"); break;
		}
	}
}

// Clear Message: Reste the filter
void butterlp_clear(t_butterlp *x)
{
	x->myFilter->clear();
}

// ATTRIBUTE: Frequency
t_max_err butterlp_setfrequency(t_butterlp *x, void *attr, long argc, t_atom *argv)
{
	x->attr_frequency = atom_getfloat(argv);
	x->myFilter->set_attr(tt_lowpass_butterworth::k_frequency, x->attr_frequency);

	return MAX_ERR_NONE;
	#pragma unused(attr)
}

// Perform Method: Mono
t_int *butterlp_perform(t_int *w)
{
	t_butterlp *x = (t_butterlp *)(w[1]);
	x->signal_in[0]->set_vector((t_float *)(w[2]));
	x->signal_out[0]->set_vector((t_float *)(w[3]));
	x->signal_in[0]->vectorsize = (int)(w[4]);

	x->myFilter->dsp_vector_calc(x->signal_in[0], x->signal_out[0]);

	return (w+5);
}

// DSP Method
void butterlp_dsp(t_butterlp *x, t_signal **sp, short *count)
{
	x->myFilter->set_sr((int)sp[0]->s_sr);
	x->myFilter->clear();

	dsp_add(butterlp_perform, 4, x, sp[0]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "thread.hh"
#include <sys/time.h>
#include <sys/types.h>
#include <algorithm>
#include <list>

namespace Rapicorn {

struct timespec
Cond::abstime (int64 usecs)
{
  struct timespec ts;
  if (usecs >= 0)
    {
      struct timeval now;
      gettimeofday (&now, NULL);
      const int64 secs = usecs / 1000000;
      int64 abs_sec = now.tv_sec + secs;
      usecs -= secs * 1000000;
      int64 abs_usec = now.tv_usec + usecs;
      if (abs_usec >= 1000000) // handle overflow from addition
        {
          abs_usec -= 1000000;
          abs_sec += 1;
        }
      ts.tv_sec = abs_sec;
      ts.tv_nsec = 1000 * abs_usec;
    }
  else
    {
      ts.tv_sec = ~time_t (0);
      ts.tv_nsec = 0;
    }
  return ts;
}

namespace ThisThread {

/** This function may be called before Rapicorn is initialized. */
int
online_cpus ()
{
  static int cpus = 0;
  if (!cpus)
    cpus = sysconf (_SC_NPROCESSORS_ONLN);
  return cpus;
}

/** This function may be called before Rapicorn is initialized. */
int
affinity ()
{
  pthread_t thread = pthread_self();
  cpu_set_t cpuset;
  if (pthread_getaffinity_np (thread, sizeof (cpu_set_t), &cpuset) != 0)
    {
      DEBUG ("pthread_getaffinity_np: %s", strerror());
      CPU_ZERO (&cpuset);
    }
  for (uint j = 0; j < CPU_SETSIZE; j++)
    if (CPU_ISSET (j, &cpuset))
      return j;
  return -1;
}

/** This function may be called before Rapicorn is initialized. */
void
affinity (int cpu)
{
  pthread_t thread = pthread_self();
  cpu_set_t cpuset;
  if (cpu >= 0 && cpu < CPU_SETSIZE)
    {
      CPU_ZERO (&cpuset);
      CPU_SET (cpu, &cpuset);
      if (pthread_setaffinity_np (thread, sizeof (cpu_set_t), &cpuset) != 0)
        DEBUG ("pthread_setaffinity_np: %s", strerror());
    }
}

int
thread_pid ()
{
  int tid = -1;
#if     defined (__linux__) && defined (__NR_gettid)    /* present on linux >= 2.4.20 */
  tid = syscall (__NR_gettid);
#endif
  if (tid < 0)
    tid = process_pid();
  return tid;
}

int
process_pid ()
{
  return getpid();
}

} // ThisThread

namespace Lib {

struct OnceData {
  Mutex                     mutex;
  Cond                      cond;
  std::list<void volatile*> list;
};

} // Lib

static Atomic<Lib::OnceData*> static_once_data = NULL;

namespace Lib {

static inline OnceData&
atomic_once_data ()
{
  OnceData *od = static_once_data.load();
  if (LIKELY (od != NULL))
    return *od;
  od = new OnceData;
  if (!static_once_data.cas (NULL, od))
    delete od;
  return *static_once_data.load();
}

void
once_list_enter()
{
  OnceData &once_data = atomic_once_data();
  once_data.mutex.lock();
}

bool
once_list_bounce (volatile void *ptr)
{
  OnceData &once_data = atomic_once_data();
  bool ptr_listed = false;
  if (ptr)
    {
      if (find (once_data.list.begin(), once_data.list.end(), ptr) == once_data.list.end())
        {
          ptr_listed = true;
          once_data.list.push_front (ptr);
        }
      else
        do
          once_data.cond.wait (once_data.mutex);
        while (find (once_data.list.begin(), once_data.list.end(), ptr) != once_data.list.end());
    }
  once_data.mutex.unlock();
  return ptr_listed;
}

bool
once_list_leave (volatile void *ptr)
{
  OnceData &once_data = atomic_once_data();
  once_data.mutex.lock();
  std::list<volatile void *>::iterator it = find (once_data.list.begin(), once_data.list.end(), ptr);
  bool found_removed = it != once_data.list.end();
  if (found_removed)
    once_data.list.erase (it);
  once_data.cond.broadcast();
  once_data.mutex.unlock();
  return found_removed;
}

} // Lib
} // Rapicorn
<commit_msg>RCORE: allow affinity debugging<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "thread.hh"
#include "strings.hh"
#include <sys/time.h>
#include <sys/types.h>
#include <algorithm>
#include <list>

#define TDEBUG(...)     RAPICORN_KEY_DEBUG ("Threading", __VA_ARGS__)

namespace Rapicorn {

struct timespec
Cond::abstime (int64 usecs)
{
  struct timespec ts;
  if (usecs >= 0)
    {
      struct timeval now;
      gettimeofday (&now, NULL);
      const int64 secs = usecs / 1000000;
      int64 abs_sec = now.tv_sec + secs;
      usecs -= secs * 1000000;
      int64 abs_usec = now.tv_usec + usecs;
      if (abs_usec >= 1000000) // handle overflow from addition
        {
          abs_usec -= 1000000;
          abs_sec += 1;
        }
      ts.tv_sec = abs_sec;
      ts.tv_nsec = 1000 * abs_usec;
    }
  else
    {
      ts.tv_sec = ~time_t (0);
      ts.tv_nsec = 0;
    }
  return ts;
}

namespace ThisThread {

/** This function may be called before Rapicorn is initialized. */
int
online_cpus ()
{
  static int cpus = 0;
  if (!cpus)
    cpus = sysconf (_SC_NPROCESSORS_ONLN);
  return cpus;
}

/** This function may be called before Rapicorn is initialized. */
int
affinity ()
{
  pthread_t thread = pthread_self();
  cpu_set_t cpuset;
  if (pthread_getaffinity_np (thread, sizeof (cpu_set_t), &cpuset) == 0)
    errno = 0;
  else
    CPU_ZERO (&cpuset);
  int cpu = -1;
  for (uint j = 0; j < CPU_SETSIZE; j++)
    if (CPU_ISSET (j, &cpuset))
      {
        cpu = j;
        break;
      }
  TDEBUG ("thread(%d/%d): pthread_getaffinity_np: %s", thread_pid(), process_pid(),
          errno ? strerror() : string_printf ("%d", cpu).c_str());
  return cpu;
}

/** This function may be called before Rapicorn is initialized. */
void
affinity (int cpu)
{
  pthread_t thread = pthread_self();
  cpu_set_t cpuset;
  if (cpu >= 0 && cpu < CPU_SETSIZE)
    {
      CPU_ZERO (&cpuset);
      CPU_SET (cpu, &cpuset);
      if (pthread_setaffinity_np (thread, sizeof (cpu_set_t), &cpuset) == 0)
        errno = 0;
      TDEBUG ("thread(%d/%d): pthread_setaffinity_np: %s", thread_pid(), process_pid(),
              errno ? strerror() : string_printf ("%d", cpu).c_str());
    }
}

int
thread_pid ()
{
  int tid = -1;
#if     defined (__linux__) && defined (__NR_gettid)    /* present on linux >= 2.4.20 */
  tid = syscall (__NR_gettid);
#endif
  if (tid < 0)
    tid = process_pid();
  return tid;
}

int
process_pid ()
{
  return getpid();
}

} // ThisThread

namespace Lib {

struct OnceData {
  Mutex                     mutex;
  Cond                      cond;
  std::list<void volatile*> list;
};

} // Lib

static Atomic<Lib::OnceData*> static_once_data = NULL;

namespace Lib {

static inline OnceData&
atomic_once_data ()
{
  OnceData *od = static_once_data.load();
  if (LIKELY (od != NULL))
    return *od;
  od = new OnceData;
  if (!static_once_data.cas (NULL, od))
    delete od;
  return *static_once_data.load();
}

void
once_list_enter()
{
  OnceData &once_data = atomic_once_data();
  once_data.mutex.lock();
}

bool
once_list_bounce (volatile void *ptr)
{
  OnceData &once_data = atomic_once_data();
  bool ptr_listed = false;
  if (ptr)
    {
      if (find (once_data.list.begin(), once_data.list.end(), ptr) == once_data.list.end())
        {
          ptr_listed = true;
          once_data.list.push_front (ptr);
        }
      else
        do
          once_data.cond.wait (once_data.mutex);
        while (find (once_data.list.begin(), once_data.list.end(), ptr) != once_data.list.end());
    }
  once_data.mutex.unlock();
  return ptr_listed;
}

bool
once_list_leave (volatile void *ptr)
{
  OnceData &once_data = atomic_once_data();
  once_data.mutex.lock();
  std::list<volatile void *>::iterator it = find (once_data.list.begin(), once_data.list.end(), ptr);
  bool found_removed = it != once_data.list.end();
  if (found_removed)
    once_data.list.erase (it);
  once_data.cond.broadcast();
  once_data.mutex.unlock();
  return found_removed;
}

} // Lib
} // Rapicorn
<|endoftext|>