<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <chrono>

#ifndef DLL_NO_TIMERS

#include <iosfwd>
#include <iomanip>
#include <sstream>

#endif

namespace dll {

/*!
 * \brief Utility for a simple timer
 */
struct stop_timer {
    std::chrono::time_point<std::chrono::steady_clock> start_time; ///< The start time

    /*!
     * \brief Start the timer
     */
    void start() {
        start_time = std::chrono::steady_clock::now();
    }

    /*!
     * \brief Stop the timer and get the elapsed since start
     * \return elapsed time since start()
     */
    size_t stop() const {
        auto end = std::chrono::steady_clock::now();
        return std::chrono::duration_cast<std::chrono::milliseconds>(end - start_time).count();
    }
};

#ifdef DLL_NO_TIMERS

/*!
 * \brief Dump the values of the timer on the console.
 *
 * This has no effect if the timers were disabled.
 */
inline void dump_timers() {
    //No timers
}

struct auto_timer {
    auto_timer(const char* /*name*/) {}
};

#else

constexpr size_t max_timers = 64; ///< The maximum number of timers

/*!
 * \brief A timer
 */
struct timer_t {
    const char* name;             ///< The name of the timer
    std::atomic<size_t> count;    ///< The number of times it was incremented
    std::atomic<size_t> duration; ///< The total duration

    /*!
     * \brief Initialize an empty counter
     */
    timer_t()
            : name(nullptr), count(0), duration(0) {}

    /*!
     * \brief Copy a timer
     */
    timer_t(const timer_t& rhs)
            : name(rhs.name), count(rhs.count.load()), duration(rhs.duration.load()) {}

    /*!
     * \brief Copy assign a timer
     */
    timer_t& operator=(const timer_t& rhs) {
        if (&rhs != this) {
            name     = rhs.name;
            count    = rhs.count.load();
            duration = rhs.duration.load();
        }

        return *this;
    }

    /*!
     * \brief Move construct a timer
     */
    timer_t(timer_t&& rhs)
            : name(std::move(rhs.name)), count(rhs.count.load()), duration(rhs.duration.load()) {}

    /*!
     * \brief Move assign a timer
     */
    timer_t& operator=(timer_t&& rhs) {
        if (&rhs != this) {
            name     = std::move(rhs.name);
            count    = rhs.count.load();
            duration = rhs.duration.load();
        }

        return *this;
    }
};

/*!
 * \brief The structure holding all the timers
 */
struct timers_t {
    std::array<timer_t, max_timers> timers; ///< The timers
    std::mutex lock; ///< The lock to protect the timers

    /*!
     * \brief Reset the status of the timers
     */
    void reset(){
        std::lock_guard<std::mutex> l(lock);

        for(auto& timer : timers){
            timer.name = nullptr;
            timer.duration = 0;
            timer.count = 0;
        }
    }
};

/*!
 * \brief Get a reference to the timer structure
 */
inline timers_t& get_timers() {
    static timers_t timers;
    return timers;
}

inline std::string to_string_precision(double duration, int precision = 6) {
    std::ostringstream out;
    out << std::setprecision(precision) << duration;
    return out.str();
}

inline std::string duration_str(double duration, int precision = 6) {
    if (duration > 1000.0 * 1000.0 * 1000.0) {
        return to_string_precision(duration / (1000.0 * 1000.0 * 1000.0), precision) + "s";
    } else if (duration > 1000.0 * 1000.0) {
        return to_string_precision(duration / (1000.0 * 1000.0), precision) + "ms";
    } else if (duration > 1000.0) {
        return to_string_precision(duration / 1000.0, precision) + "us";
    } else {
        return to_string_precision(duration, precision) + "ns";
    }
}

/*!
 * \brief Reset all timers
 */
inline void reset_timers() {
    decltype(auto) timers = get_timers();
    timers.reset();
}

/*!
 * \brief Dump the values of the timer on the console.
 *
 * This has no effect if the timers were disabled.
 */
inline void dump_timers() {
    decltype(auto) timers = get_timers().timers;

    //Sort the timers by duration (DESC)
    std::sort(timers.begin(), timers.end(), [](auto& left, auto& right) {
        return left.duration > right.duration;
    });

    // Print all the used timers
    for (decltype(auto) timer : timers) {
        if (timer.name) {
            size_t count = timer.count;
            size_t duration = timer.duration;
            std::cout << timer.name << "(" << count << ") : "
                      << duration_str(duration)
                      << " (" << duration_str(duration / count) << ")" << std::endl;
        }
    }
}

/*!
 * \brief Dump all timers values to the console, with percentage of time from
 * the total.
 *
 * The total is the counter with the maximum total time
 */
inline void dump_timers_one() {
    decltype(auto) timers = get_timers().timers;

    if(timers.empty()){
        return;
    }

    //Sort the timers by duration (DESC)
    std::sort(timers.begin(), timers.end(), [](auto& left, auto& right) {
        return left.duration > right.duration;
    });

    double total_duration = timers.front().duration.load();

    // Print all the used timers
    for (decltype(auto) timer : timers) {
        if (timer.name) {
            size_t count = timer.count;
            size_t duration = timer.duration;
            std::cout << timer.name << "(" << count << ") : "
                      << duration_str(duration)
                      << " (" << 100.0 * (duration / total_duration) << "%, " << duration_str(duration / count) << ")" << std::endl;
        }
    }
}

/*!
 * \brief Automatic timer with RAII.
 */
struct auto_timer {
    const char* name;                               ///< The name of the timer
    std::chrono::time_point<std::chrono::steady_clock> start; ///< The start time
    std::chrono::time_point<std::chrono::steady_clock> end;   ///< The end time

    /*!
     * \brief Create an auto_timer witht the given name
     * \param name The name of the timer
     */
    auto_timer(const char* name) : name(name) {
        start = std::chrono::steady_clock::now();
    }

    /*!
     * \brief Destructs the timer, effectively incrementing the timer.
     */
    ~auto_timer() {
        end           = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();

        decltype(auto) timers = get_timers();

        for (decltype(auto) timer : timers.timers) {
            if (timer.name == name) {
                timer.duration += duration;
                ++timer.count;

                return;
            }
        }

        std::lock_guard<std::mutex> lock(timers.lock);

        for (decltype(auto) timer : timers.timers) {
            if (timer.name == name) {
                timer.duration += duration;
                ++timer.count;

                return;
            }
        }

        for (decltype(auto) timer : timers.timers) {
            if (!timer.name) {
                timer.name     = name;
                timer.duration = duration;
                timer.count    = 1;

                return;
            }
        }

        std::cerr << "Unable to register timer " << name << std::endl;
    }
};

#endif

} //end of namespace dll
<commit_msg>Add support for pretty printing the timers<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <chrono>

#ifndef DLL_NO_TIMERS

#include <iosfwd>
#include <iomanip>
#include <sstream>

#endif

namespace dll {

/*!
 * \brief Utility for a simple timer
 */
struct stop_timer {
    std::chrono::time_point<std::chrono::steady_clock> start_time; ///< The start time

    /*!
     * \brief Start the timer
     */
    void start() {
        start_time = std::chrono::steady_clock::now();
    }

    /*!
     * \brief Stop the timer and get the elapsed since start
     * \return elapsed time since start()
     */
    size_t stop() const {
        auto end = std::chrono::steady_clock::now();
        return std::chrono::duration_cast<std::chrono::milliseconds>(end - start_time).count();
    }
};

#ifdef DLL_NO_TIMERS

/*!
 * \brief Dump the values of the timer on the console.
 *
 * This has no effect if the timers were disabled.
 */
inline void dump_timers() {
    //No timers
}

struct auto_timer {
    auto_timer(const char* /*name*/) {}
};

#else

constexpr size_t max_timers = 64; ///< The maximum number of timers

/*!
 * \brief A timer
 */
struct timer_t {
    const char* name;             ///< The name of the timer
    std::atomic<size_t> count;    ///< The number of times it was incremented
    std::atomic<size_t> duration; ///< The total duration

    /*!
     * \brief Initialize an empty counter
     */
    timer_t()
            : name(nullptr), count(0), duration(0) {}

    /*!
     * \brief Copy a timer
     */
    timer_t(const timer_t& rhs)
            : name(rhs.name), count(rhs.count.load()), duration(rhs.duration.load()) {}

    /*!
     * \brief Copy assign a timer
     */
    timer_t& operator=(const timer_t& rhs) {
        if (&rhs != this) {
            name     = rhs.name;
            count    = rhs.count.load();
            duration = rhs.duration.load();
        }

        return *this;
    }

    /*!
     * \brief Move construct a timer
     */
    timer_t(timer_t&& rhs)
            : name(std::move(rhs.name)), count(rhs.count.load()), duration(rhs.duration.load()) {}

    /*!
     * \brief Move assign a timer
     */
    timer_t& operator=(timer_t&& rhs) {
        if (&rhs != this) {
            name     = std::move(rhs.name);
            count    = rhs.count.load();
            duration = rhs.duration.load();
        }

        return *this;
    }
};

/*!
 * \brief The structure holding all the timers
 */
struct timers_t {
    std::array<timer_t, max_timers> timers; ///< The timers
    std::mutex lock; ///< The lock to protect the timers

    /*!
     * \brief Reset the status of the timers
     */
    void reset(){
        std::lock_guard<std::mutex> l(lock);

        for(auto& timer : timers){
            timer.name = nullptr;
            timer.duration = 0;
            timer.count = 0;
        }
    }
};

/*!
 * \brief Get a reference to the timer structure
 */
inline timers_t& get_timers() {
    static timers_t timers;
    return timers;
}

inline std::string to_string_precision(double duration, int precision = 6) {
    std::ostringstream out;
    out << std::setprecision(precision) << duration;
    return out.str();
}

inline std::string duration_str(double duration, int precision = 6) {
    if (duration > 1000.0 * 1000.0 * 1000.0) {
        return to_string_precision(duration / (1000.0 * 1000.0 * 1000.0), precision) + "s";
    } else if (duration > 1000.0 * 1000.0) {
        return to_string_precision(duration / (1000.0 * 1000.0), precision) + "ms";
    } else if (duration > 1000.0) {
        return to_string_precision(duration / 1000.0, precision) + "us";
    } else {
        return to_string_precision(duration, precision) + "ns";
    }
}

/*!
 * \brief Reset all timers
 */
inline void reset_timers() {
    decltype(auto) timers = get_timers();
    timers.reset();
}

/*!
 * \brief Dump the values of the timer on the console.
 *
 * This has no effect if the timers were disabled.
 */
inline void dump_timers() {
    decltype(auto) timers = get_timers().timers;

    //Sort the timers by duration (DESC)
    std::sort(timers.begin(), timers.end(), [](auto& left, auto& right) {
        return left.duration > right.duration;
    });

    // Print all the used timers
    for (decltype(auto) timer : timers) {
        if (timer.name) {
            size_t count = timer.count;
            size_t duration = timer.duration;
            std::cout << timer.name << "(" << count << ") : "
                      << duration_str(duration)
                      << " (" << duration_str(duration / count) << ")" << std::endl;
        }
    }
}

/*!
 * \brief Dump all timers values to the console, with percentage of time from
 * the total.
 *
 * The total is the counter with the maximum total time
 */
inline void dump_timers_one() {
    decltype(auto) timers = get_timers().timers;

    if(timers.empty()){
        return;
    }

    //Sort the timers by duration (DESC)
    std::sort(timers.begin(), timers.end(), [](auto& left, auto& right) {
        return left.duration > right.duration;
    });

    double total_duration = timers.front().duration.load();

    // Print all the used timers
    for (decltype(auto) timer : timers) {
        if (timer.name) {
            size_t count = timer.count;
            size_t duration = timer.duration;
            std::cout << timer.name << "(" << count << ") : "
                      << duration_str(duration)
                      << " (" << 100.0 * (duration / total_duration) << "%, " << duration_str(duration / count) << ")" << std::endl;
        }
    }
}

/*!
 * \brief Dump all timers values to the console in the form of a table.
 */
inline void dump_timers_pretty() {
    decltype(auto) timers = get_timers().timers;

    if(timers.empty()){
        std::cout << "No timers have been recorded!" << std::endl;
        return;
    }

    //Sort the timers by duration (DESC)
    std::sort(timers.begin(), timers.end(), [](auto& left, auto& right) {
        return left.duration > right.duration;
    });

    double total_duration = timers.front().duration.load();

    constexpr size_t columns = 5;

    std::string column_name[columns];
    column_name[0] = "%";
    column_name[1] = "Timer";
    column_name[2] = "Count";
    column_name[3] = "Total";
    column_name[4] = "Average";

    size_t column_length[columns];
    column_length[0] = 8;
    column_length[1] = column_name[1].size();
    column_length[2] = column_name[2].size();
    column_length[3] = column_name[3].size();
    column_length[4] = column_name[4].size();

    // Compute the width of each column
    for (decltype(auto) timer : timers) {
        if (timer.name) {
            size_t count = timer.count;
            size_t duration = timer.duration;

            column_length[1] = std::max(column_length[1], std::string(timer.name).size());
            column_length[2] = std::max(column_length[2], std::to_string(count).size());
            column_length[3] = std::max(column_length[3], duration_str(duration).size());
            column_length[4] = std::max(column_length[4], duration_str(duration / count).size());
        }
    }

    const size_t line_length = (columns + 1) * 1 + 2 + (columns - 1) * 2 + std::accumulate(column_length, column_length + columns, 0);

    std::cout << std::string(line_length, '-') << '\n';

    printf("| %-*s | %-*s | %-*s | %-*s | %-*s |\n",
        int(column_length[0]), column_name[0].c_str(),
        int(column_length[1]), column_name[1].c_str(),
        int(column_length[2]), column_name[2].c_str(),
        int(column_length[3]), column_name[3].c_str(),
        int(column_length[4]), column_name[4].c_str());

    std::cout << std::string(line_length, '-') << '\n';

    // Print all the used timers
    for (decltype(auto) timer : timers) {
        if (timer.name) {
            size_t count = timer.count;
            size_t duration = timer.duration;

            printf("| %*.3f%% | %-*s | %-*s | %-*s | %-*s |\n",
                int(column_length[0] - 1), 100.0 * (duration / double(total_duration)),
                int(column_length[1]), timer.name,
                int(column_length[2]), std::to_string(count).c_str(),
                int(column_length[3]), duration_str(duration).c_str(),
                int(column_length[4]), duration_str(duration / count).c_str());
        }
    }

    std::cout << std::string(line_length, '-') << '\n';
}

/*!
 * \brief Automatic timer with RAII.
 */
struct auto_timer {
    const char* name;                               ///< The name of the timer
    std::chrono::time_point<std::chrono::steady_clock> start; ///< The start time
    std::chrono::time_point<std::chrono::steady_clock> end;   ///< The end time

    /*!
     * \brief Create an auto_timer witht the given name
     * \param name The name of the timer
     */
    auto_timer(const char* name) : name(name) {
        start = std::chrono::steady_clock::now();
    }

    /*!
     * \brief Destructs the timer, effectively incrementing the timer.
     */
    ~auto_timer() {
        end           = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();

        decltype(auto) timers = get_timers();

        for (decltype(auto) timer : timers.timers) {
            if (timer.name == name) {
                timer.duration += duration;
                ++timer.count;

                return;
            }
        }

        std::lock_guard<std::mutex> lock(timers.lock);

        for (decltype(auto) timer : timers.timers) {
            if (timer.name == name) {
                timer.duration += duration;
                ++timer.count;

                return;
            }
        }

        for (decltype(auto) timer : timers.timers) {
            if (!timer.name) {
                timer.name     = name;
                timer.duration = duration;
                timer.count    = 1;

                return;
            }
        }

        std::cerr << "Unable to register timer " << name << std::endl;
    }
};

#endif

} //end of namespace dll
<|endoftext|>


<commit_before>/*

Copyright (c) 2003-2012, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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.

*/

#ifndef TORRENT_FILE_HPP_INCLUDED
#define TORRENT_FILE_HPP_INCLUDED

#include <memory>
#include <string>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/noncopyable.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/error_code.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"

#ifdef TORRENT_WINDOWS
// windows part
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winioctl.h>
#include <sys/types.h>
#else
// posix part
#define _FILE_OFFSET_BITS 64

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif

#include <unistd.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h> // for DIR

#undef _FILE_OFFSET_BITS

#endif

namespace libtorrent
{
	struct file_status
	{
		size_type file_size;
		time_t atime;
		time_t mtime;
		time_t ctime;
		enum {
#if defined TORRENT_WINDOWS
			fifo = 0x1000, // named pipe (fifo)
			character_special = 0x2000,  // character special
			directory = 0x4000,  // directory
			regular_file = 0x8000  // regular
#else
			fifo = 0010000, // named pipe (fifo)
			character_special = 0020000,  // character special
			directory = 0040000,  // directory
			block_special = 0060000,  // block special
			regular_file = 0100000,  // regular
			link = 0120000,  // symbolic link
			socket = 0140000  // socket
#endif
		} modes_t;
		int mode;
	};

	// flags for stat_file
	enum { dont_follow_links = 1 };
	TORRENT_EXTRA_EXPORT void stat_file(std::string f, file_status* s
		, error_code& ec, int flags = 0);
	TORRENT_EXTRA_EXPORT void rename(std::string const& f
		, std::string const& newf, error_code& ec);
	TORRENT_EXTRA_EXPORT void create_directories(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void create_directory(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void remove_all(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void remove(std::string const& f, error_code& ec);
	TORRENT_EXTRA_EXPORT bool exists(std::string const& f);
	TORRENT_EXTRA_EXPORT size_type file_size(std::string const& f);
	TORRENT_EXTRA_EXPORT bool is_directory(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void recursive_copy(std::string const& old_path
		, std::string const& new_path, error_code& ec);
	TORRENT_EXTRA_EXPORT void copy_file(std::string const& f
		, std::string const& newf, error_code& ec);

	TORRENT_EXTRA_EXPORT std::string split_path(std::string const& f);
	TORRENT_EXTRA_EXPORT char const* next_path_element(char const* p);
	TORRENT_EXTRA_EXPORT std::string extension(std::string const& f);
	TORRENT_EXTRA_EXPORT void replace_extension(std::string& f, std::string const& ext);
	TORRENT_EXTRA_EXPORT bool is_root_path(std::string const& f);
	TORRENT_EXTRA_EXPORT std::string parent_path(std::string const& f);
	TORRENT_EXTRA_EXPORT bool has_parent_path(std::string const& f);
	TORRENT_EXTRA_EXPORT std::string filename(std::string const& f);
	TORRENT_EXTRA_EXPORT std::string combine_path(std::string const& lhs
		, std::string const& rhs);
	TORRENT_EXTRA_EXPORT std::string complete(std::string const& f);
	TORRENT_EXTRA_EXPORT bool is_complete(std::string const& f);
	TORRENT_EXTRA_EXPORT std::string current_working_directory();
#if TORRENT_USE_UNC_PATHS
	TORRENT_EXTRA_EXPORT std::string canonicalize_path(std::string const& f);
#endif

	class TORRENT_EXTRA_EXPORT directory : public boost::noncopyable
	{
	public:
		directory(std::string const& path, error_code& ec);
		~directory();
		void next(error_code& ec);
		std::string file() const;
		bool done() const { return m_done; }
	private:
#ifdef TORRENT_WINDOWS
		HANDLE m_handle;
#if TORRENT_USE_WSTRING
		WIN32_FIND_DATAW m_fd;
#else
		WIN32_FIND_DATAA m_fd;
#endif
#else
		DIR* m_handle;
		// the dirent struct contains a zero-sized
		// array at the end, it will end up referring
		// to the m_name field
		struct dirent m_dirent;
		char m_name[TORRENT_MAX_PATH + 1]; // +1 to make room for null
#endif
		bool m_done;
	};

	struct TORRENT_EXTRA_EXPORT file: boost::noncopyable, intrusive_ptr_base<file>
	{
		enum
		{
			// when a file is opened with no_buffer
			// file offsets have to be aligned to
			// pos_alignment() and buffer addresses
			// to buf_alignment() and read/write sizes
			// to size_alignment()
			read_only = 0,
			write_only = 1,
			read_write = 2,
			rw_mask = read_only | write_only | read_write,
			no_buffer = 4,
			sparse = 8,
			no_atime = 16,
			random_access = 32,
			lock_file = 64,

			attribute_hidden = 0x1000,
			attribute_executable = 0x2000,
			attribute_mask = attribute_hidden | attribute_executable
		};

#ifdef TORRENT_WINDOWS
		struct iovec_t
		{
			void* iov_base;
			size_t iov_len;
		};
#else
		typedef iovec iovec_t;
#endif

		// use a typedef for the type of iovec_t::iov_base
		// since it may differ
#ifdef TORRENT_SOLARIS
		typedef char* iovec_base_t;
#else
		typedef void* iovec_base_t;
#endif

		file();
		file(std::string const& p, int m, error_code& ec);
		~file();

		bool open(std::string const& p, int m, error_code& ec);
		bool is_open() const;
		void close();
		bool set_size(size_type size, error_code& ec);

		int open_mode() const { return m_open_mode; }

		// when opened in unbuffered mode, this is the
		// required alignment of file_offsets. i.e.
		// any (file_offset & (pos_alignment()-1)) == 0
		// is a precondition to read and write operations
		int pos_alignment() const;

		// when opened in unbuffered mode, this is the
		// required alignment of buffer addresses
		int buf_alignment() const;

		// read/write buffer sizes needs to be aligned to
		// this when in unbuffered mode
		int size_alignment() const;

		size_type writev(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
		size_type readv(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
		void hint_read(size_type file_offset, int len);

		size_type get_size(error_code& ec) const;

		// return the offset of the first byte that
		// belongs to a data-region
		size_type sparse_end(size_type start) const;

		size_type phys_offset(size_type offset);

#ifdef TORRENT_WINDOWS
		HANDLE native_handle() const { return m_file_handle; }
#else
		int native_handle() const { return m_fd; }
#endif

	private:

#ifdef TORRENT_WINDOWS
		HANDLE m_file_handle;
#if TORRENT_USE_WSTRING
		std::wstring m_path;
#else
		std::string m_path;
#endif // TORRENT_USE_WSTRING
#else // TORRENT_WINDOWS
		int m_fd;
#endif // TORRENT_WINDOWS

#if defined TORRENT_WINDOWS || defined TORRENT_LINUX || defined TORRENT_DEBUG
		static void init_file();
		static int m_page_size;
#endif
		int m_open_mode;
#if defined TORRENT_WINDOWS || defined TORRENT_LINUX
		mutable int m_sector_size;
#endif
#if defined TORRENT_WINDOWS
		mutable int m_cluster_size;
#endif
	};

}

#endif // TORRENT_FILE_HPP_INCLUDED

<commit_msg>fix python binding with shared linking<commit_after>/*

Copyright (c) 2003-2012, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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.

*/

#ifndef TORRENT_FILE_HPP_INCLUDED
#define TORRENT_FILE_HPP_INCLUDED

#include <memory>
#include <string>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/noncopyable.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/error_code.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"

#ifdef TORRENT_WINDOWS
// windows part
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winioctl.h>
#include <sys/types.h>
#else
// posix part
#define _FILE_OFFSET_BITS 64

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif

#include <unistd.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h> // for DIR

#undef _FILE_OFFSET_BITS

#endif

namespace libtorrent
{
	struct file_status
	{
		size_type file_size;
		time_t atime;
		time_t mtime;
		time_t ctime;
		enum {
#if defined TORRENT_WINDOWS
			fifo = 0x1000, // named pipe (fifo)
			character_special = 0x2000,  // character special
			directory = 0x4000,  // directory
			regular_file = 0x8000  // regular
#else
			fifo = 0010000, // named pipe (fifo)
			character_special = 0020000,  // character special
			directory = 0040000,  // directory
			block_special = 0060000,  // block special
			regular_file = 0100000,  // regular
			link = 0120000,  // symbolic link
			socket = 0140000  // socket
#endif
		} modes_t;
		int mode;
	};

	// flags for stat_file
	enum { dont_follow_links = 1 };
	TORRENT_EXTRA_EXPORT void stat_file(std::string f, file_status* s
		, error_code& ec, int flags = 0);
	TORRENT_EXTRA_EXPORT void rename(std::string const& f
		, std::string const& newf, error_code& ec);
	TORRENT_EXTRA_EXPORT void create_directories(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void create_directory(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void remove_all(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void remove(std::string const& f, error_code& ec);
	TORRENT_EXTRA_EXPORT bool exists(std::string const& f);
	TORRENT_EXTRA_EXPORT size_type file_size(std::string const& f);
	TORRENT_EXTRA_EXPORT bool is_directory(std::string const& f
		, error_code& ec);
	TORRENT_EXTRA_EXPORT void recursive_copy(std::string const& old_path
		, std::string const& new_path, error_code& ec);
	TORRENT_EXTRA_EXPORT void copy_file(std::string const& f
		, std::string const& newf, error_code& ec);

	TORRENT_EXTRA_EXPORT std::string split_path(std::string const& f);
	TORRENT_EXTRA_EXPORT char const* next_path_element(char const* p);
	TORRENT_EXTRA_EXPORT std::string extension(std::string const& f);
	TORRENT_EXTRA_EXPORT void replace_extension(std::string& f, std::string const& ext);
	TORRENT_EXTRA_EXPORT bool is_root_path(std::string const& f);
	// used by create_torrent.hpp
	TORRENT_EXPORT std::string parent_path(std::string const& f);
	TORRENT_EXTRA_EXPORT bool has_parent_path(std::string const& f);
	// used by create_torrent.hpp
	TORRENT_EXPORT std::string filename(std::string const& f);
	TORRENT_EXTRA_EXPORT std::string combine_path(std::string const& lhs
		, std::string const& rhs);
	// used by create_torrent.hpp
	TORRENT_EXPORT std::string complete(std::string const& f);
	TORRENT_EXTRA_EXPORT bool is_complete(std::string const& f);
	TORRENT_EXTRA_EXPORT std::string current_working_directory();
#if TORRENT_USE_UNC_PATHS
	TORRENT_EXTRA_EXPORT std::string canonicalize_path(std::string const& f);
#endif

	class TORRENT_EXTRA_EXPORT directory : public boost::noncopyable
	{
	public:
		directory(std::string const& path, error_code& ec);
		~directory();
		void next(error_code& ec);
		std::string file() const;
		bool done() const { return m_done; }
	private:
#ifdef TORRENT_WINDOWS
		HANDLE m_handle;
#if TORRENT_USE_WSTRING
		WIN32_FIND_DATAW m_fd;
#else
		WIN32_FIND_DATAA m_fd;
#endif
#else
		DIR* m_handle;
		// the dirent struct contains a zero-sized
		// array at the end, it will end up referring
		// to the m_name field
		struct dirent m_dirent;
		char m_name[TORRENT_MAX_PATH + 1]; // +1 to make room for null
#endif
		bool m_done;
	};

	struct TORRENT_EXTRA_EXPORT file: boost::noncopyable, intrusive_ptr_base<file>
	{
		enum
		{
			// when a file is opened with no_buffer
			// file offsets have to be aligned to
			// pos_alignment() and buffer addresses
			// to buf_alignment() and read/write sizes
			// to size_alignment()
			read_only = 0,
			write_only = 1,
			read_write = 2,
			rw_mask = read_only | write_only | read_write,
			no_buffer = 4,
			sparse = 8,
			no_atime = 16,
			random_access = 32,
			lock_file = 64,

			attribute_hidden = 0x1000,
			attribute_executable = 0x2000,
			attribute_mask = attribute_hidden | attribute_executable
		};

#ifdef TORRENT_WINDOWS
		struct iovec_t
		{
			void* iov_base;
			size_t iov_len;
		};
#else
		typedef iovec iovec_t;
#endif

		// use a typedef for the type of iovec_t::iov_base
		// since it may differ
#ifdef TORRENT_SOLARIS
		typedef char* iovec_base_t;
#else
		typedef void* iovec_base_t;
#endif

		file();
		file(std::string const& p, int m, error_code& ec);
		~file();

		bool open(std::string const& p, int m, error_code& ec);
		bool is_open() const;
		void close();
		bool set_size(size_type size, error_code& ec);

		int open_mode() const { return m_open_mode; }

		// when opened in unbuffered mode, this is the
		// required alignment of file_offsets. i.e.
		// any (file_offset & (pos_alignment()-1)) == 0
		// is a precondition to read and write operations
		int pos_alignment() const;

		// when opened in unbuffered mode, this is the
		// required alignment of buffer addresses
		int buf_alignment() const;

		// read/write buffer sizes needs to be aligned to
		// this when in unbuffered mode
		int size_alignment() const;

		size_type writev(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
		size_type readv(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
		void hint_read(size_type file_offset, int len);

		size_type get_size(error_code& ec) const;

		// return the offset of the first byte that
		// belongs to a data-region
		size_type sparse_end(size_type start) const;

		size_type phys_offset(size_type offset);

#ifdef TORRENT_WINDOWS
		HANDLE native_handle() const { return m_file_handle; }
#else
		int native_handle() const { return m_fd; }
#endif

	private:

#ifdef TORRENT_WINDOWS
		HANDLE m_file_handle;
#if TORRENT_USE_WSTRING
		std::wstring m_path;
#else
		std::string m_path;
#endif // TORRENT_USE_WSTRING
#else // TORRENT_WINDOWS
		int m_fd;
#endif // TORRENT_WINDOWS

#if defined TORRENT_WINDOWS || defined TORRENT_LINUX || defined TORRENT_DEBUG
		static void init_file();
		static int m_page_size;
#endif
		int m_open_mode;
#if defined TORRENT_WINDOWS || defined TORRENT_LINUX
		mutable int m_sector_size;
#endif
#if defined TORRENT_WINDOWS
		mutable int m_cluster_size;
#endif
	};

}

#endif // TORRENT_FILE_HPP_INCLUDED

<|endoftext|>


<commit_before>#include "StdAfx.h"
#include "FileWriter.h"
#if defined(__unix__) || defined(__APPLE__)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
//#include <sys/mman.h>
#endif // __unix__
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

FileWriter::FileWriter(LPCWSTR _filename) : mFilename(_filename) {
}

void FileWriter::writeFile(FileMap* filemap, uint32 size) {
  if (size > filemap->getSize())
    size = filemap->getSize();
#if defined(__unix__) || defined(__APPLE__)
  int bytes_written = 0;
  FILE *file;
  char *src;

  file = fopen(mFilename, "wb");
  if (file == NULL)
    throw FileIOException("Could not open file.");

  src = (char *)filemap->getData(0);
  bytes_written = fwrite(src, 1, size ? size : filemap->getSize(), file);
  fclose(file);
  if (size != bytes_written) {
    throw FileIOException("Could not write file.");
  }

#else // __unix__
  HANDLE file_h;  // File handle
  file_h = CreateFile(mFilename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  if (file_h == INVALID_HANDLE_VALUE) {
    throw FileIOException("Could not open file.");
  }

  DWORD bytes_written;
  if (! WriteFile(file_h, filemap->getData(0), size ? size : filemap->getSize(), &bytes_written, NULL)) {
    CloseHandle(file_h);
    throw FileIOException("Could not read file.");
  }
  CloseHandle(file_h);

#endif // __unix__
}

FileWriter::~FileWriter(void) {

}

} // namespace RawSpeed
<commit_msg>fix signed/unsigned warning<commit_after>#include "StdAfx.h"
#include "FileWriter.h"
#if defined(__unix__) || defined(__APPLE__)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
//#include <sys/mman.h>
#endif // __unix__
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

FileWriter::FileWriter(LPCWSTR _filename) : mFilename(_filename) {
}

void FileWriter::writeFile(FileMap* filemap, uint32 size) {
  if (size > filemap->getSize())
    size = filemap->getSize();
#if defined(__unix__) || defined(__APPLE__)
  size_t bytes_written = 0;
  FILE *file;
  char *src;

  file = fopen(mFilename, "wb");
  if (file == NULL)
    throw FileIOException("Could not open file.");

  src = (char *)filemap->getData(0);
  bytes_written = fwrite(src, 1, size ? size : filemap->getSize(), file);
  fclose(file);
  if (size != bytes_written) {
    throw FileIOException("Could not write file.");
  }

#else // __unix__
  HANDLE file_h;  // File handle
  file_h = CreateFile(mFilename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  if (file_h == INVALID_HANDLE_VALUE) {
    throw FileIOException("Could not open file.");
  }

  DWORD bytes_written;
  if (! WriteFile(file_h, filemap->getData(0), size ? size : filemap->getSize(), &bytes_written, NULL)) {
    CloseHandle(file_h);
    throw FileIOException("Could not read file.");
  }
  CloseHandle(file_h);

#endif // __unix__
}

FileWriter::~FileWriter(void) {

}

} // namespace RawSpeed
<|endoftext|>


<commit_before>#include "controller.h"

// Constructor
//   Allows for Verbose Debugging Mode
//   @param bool debug_flag, true will enable verbose debugging
//   @warn assert will end program prematurely
//   @note axis is rendered in debugging mode
Controller::Controller(const int window_width, const int window_height, const bool debug_flag) :
  // Object construction
  renderer_(Renderer(debug_flag)),
  shaders_(renderer_.shaders()),
  camera_(Camera(shaders_, window_width, window_height)),
  sun_(Sun(camera(), debug_flag)),
  light_controller_(new LightController()),
  collision_controller_(CollisionController()),
  terrain_(new Terrain(shaders_->LightMappedGeneric)),
  road_sign_(RoadSign(shaders_, terrain_)),
  car_(AddObject(shaders_->LightMappedGeneric, "models/Pick-up_Truck/pickup_wind_alpha.obj")),
  // State and var defaults
  game_state_(kAutoDrive), light_pos_(glm::vec4(0,0,0,0)),
  frames_past_(0), frames_count_(0), delta_time_(16), is_debugging_(debug_flag) {

    is_key_pressed_hash_.reserve(256);
    is_key_pressed_hash_.resize(256);
    playSound = 1;

    rain_ = new Rain(shaders_->RainGeneric, debug_flag);
    water_ = new Water(shaders_->WaterGeneric);
    skybox_ = new Skybox(shaders_->SkyboxGeneric);

  // Add starting models
  // AddModel(shaders_->LightMappedGeneric, "models/Pick-up_Truck/pickup.obj", true);
  // AddModel(shaders_->LightMappedGeneric, "models/Car/car-n.obj", true);
  // AddModel(shaders_->LightMappedGeneric, "models/Signs_OBJ/working/curve_left.obj");
  // AddModel(shaders_->LightMappedGeneric, "models/Signs_OBJ/working/curve_right.obj");
  // AddModel(shaders_->LightMappedGeneric, "models/Signs_OBJ/working/60.obj");

}

// Adds a model to the member vector
//   @param shader, a shader class holding shader to use and uniforms
//   @param model_filename, a string containing the path of the .obj file
//   @warn the model is created on the heap and memory must be freed afterwards
Object * Controller::AddObject(const Shader &shader, const std::string &model_filename) {
  Object * object = new Model(shader, model_filename,
      glm::vec3(0.95f, 0.55f, 35.0f),     // Translation  move behind first tile (i.e. start on 2nd tile)
      glm::vec3(0.0f, 20.0f, 0.0f),       // Rotation
      glm::vec3(0.4f,  0.4f*1.6f, 0.4f),  // Scale
      60, false); // starting speed and debugging mode

  return object;
}

// Renders all models in the vector member
//   Should be called in the render loop
void Controller::Draw() {
  // Draw to shadow buffer
  glBindFramebuffer(GL_FRAMEBUFFER, renderer_.fbo()->FrameBufferShadows);
  glClear(GL_DEPTH_BUFFER_BIT);
  glViewport(0, 0, renderer_.fbo()->textureX, renderer_.fbo()->textureY);

  // Car with physics
  renderer_.RenderDepthBuffer(car_, sun_);
  // Road-signs
  const std::vector<Object*> signs = road_sign_.signs();
  const std::vector<int> active_signs = road_sign_.active_signs();

  // Unfortunately this does not work
  // for (unsigned int x = 0; x < signs.size(); ++x) {
  //   // if (active_signs[x] >= 0) // no point
  //   renderer_.RenderDepthBuffer(signs[x], sun_);
  // }
  // Terrain
  renderer_.RenderDepthBuffer(terrain_, sun_);

  // Draw to screen
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
  // Bind shadow map texture
  glBindTexture(GL_TEXTURE_2D, renderer_.fbo()->DepthTexture);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glViewport(0, 0, camera_.width(), camera_.height());

  // Ordering of renderering is very important due to transparency
  renderer_.RenderSkybox(skybox_, camera_);
  // Water
  renderer_.RenderWater(water_, car_, skybox_, camera_);
  // Terrain
  renderer_.Render(terrain_, camera_, sun_);
  // Road-signs
  for (unsigned int x = 0; x < signs.size(); ++x) {
    // if (active_signs[x] >= 0) // no point
    renderer_.Render(signs[x], camera_, sun_);
  }
  if (camera_.state() == Camera::kFirstPerson) {
    // Rain (particles)
    if (sun_.time_of_day() != 12)
      rain_->Render(camera_, car_, skybox_);
  // Car with physics
  renderer_.Render(car_, camera_, sun_);
  } else {
    // Car with physics
    renderer_.Render(car_, camera_, sun_);
    // Rain (particles)
    if (sun_.time_of_day() != 12)
      rain_->Render(camera_, car_, skybox_);
  }

  // Axis only renders in debugging mode
  renderer_.RenderAxis(camera_);
}

// Assumes SetupLighting() has been called, only updates essential light properties
void Controller::PositionLights() {
  glm::mat4 view_matrix = camera_.view_matrix();
  glm::mat4 car_mv_matrix = view_matrix * car_->model_matrix();
  // glm::mat3 norm_matrix = glm::mat3(view_matrix);

  DirectionalLight dirLight;

  dirLight.DiffuseIntensity = glm::vec3(1.00f, 1.00f, 1.00f);
  dirLight.AmbientIntensity = glm::vec3(0.50f, 0.50f, 0.50f);
  dirLight.SpecularIntensity = glm::vec3(0.35f, 0.35f, 0.40f);
  dirLight.DiffuseIntensity *= sun_.LightIntensityMultiplier();
  dirLight.AmbientIntensity *= sun_.LightIntensityMultiplier();
  // dirLight.SpecularIntensity *= 1.0f - sun_.LightIntensityMultiplier();
  // if (!sun_.IsDay()) {
  //   dirLight.SpecularIntensity.x *= 1.0f - sun_.LightIntensityMultiplier();
  //   dirLight.SpecularIntensity.y *= 1.0f - sun_.LightIntensityMultiplier();
  // }
  dirLight.Direction =  sun_.sun_direction();

  // Point lights
  std::vector<PointLight> pointLights;
  // Main car brake lights
  for (unsigned int i = 0; i < 2; i++) {
    glm::mat4 brakeLightTranslation = glm::translate(glm::mat4(1.0f), glm::vec3(-0.85f + i * 1.7f, 0.0f, -3.3f));

    PointLight brakeLight;
    brakeLight.DiffuseIntensity = glm::vec3(1.0f, 0.0f, 0.0f);
    brakeLight.Position = glm::vec3(car_mv_matrix * brakeLightTranslation * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
    brakeLight.Attenuation.Constant = 0.001f;
    brakeLight.Attenuation.Linear = 2.0f;
    brakeLight.Attenuation.Exp = 3.0f;

    if (is_key_pressed_hash_.at('s')) {
      brakeLight.Attenuation.Constant = 0.00001f;
      brakeLight.Attenuation.Linear = 0.5f;
      brakeLight.Attenuation.Exp = 3.0f;
    }

    pointLights.push_back(brakeLight);
  }

  // Spot lights
  std::vector<SpotLight> spotLights;
  // Main car headlights
  for (unsigned int i = 0; i < 2; i++) {
    glm::mat4 headlightTranslation = glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f + i * 1.0f, 0.0f, 1.45f));
    glm::mat3 headlightNormMatrix = glm::mat3(car_mv_matrix);

    SpotLight headlight;
    headlight.DiffuseIntensity = glm::vec3(1.0f, 1.0f, 1.0f);
    headlight.SpecularIntensity = glm::vec3(0.1f, 0.1f, 0.1f);
    headlight.Position = glm::vec3(car_mv_matrix * headlightTranslation * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
    headlight.Direction = headlightNormMatrix * glm::vec3(0.0f, -0.3f, 1.0f);
    headlight.CosineCutoff = cos(DEG2RAD(30.0f));
    headlight.Attenuation.Constant = 0.3f;
    headlight.Attenuation.Linear = 0.01f;
    headlight.Attenuation.Exp = 0.01f;

    if (is_key_pressed_hash_.at('r')) {
      headlight.DiffuseIntensity = glm::vec3(0.0f, 0.0f, 0.0f);
      headlight.SpecularIntensity = glm::vec3(0.0f, 0.0f, 0.0f);
    }

    spotLights.push_back(headlight);
  }

  light_controller_->SetDirectionalLight(car_->shader()->Id, dirLight);
  light_controller_->SetSpotLights(water_->shader().Id, spotLights.size(), &spotLights[0]);
  light_controller_->SetDirectionalLight(water_->shader().Id, dirLight);

  light_controller_->SetPointLights(car_->shader()->Id, pointLights.size(), &pointLights[0]);
  light_controller_->SetSpotLights(car_->shader()->Id, spotLights.size(), &spotLights[0]);
}

// The main control tick
//   Controls everything: camera, inputs, physics, collisions
void Controller::UpdateGame() {
  // Lights need to be transformed with view/normal matrix
  PositionLights();
  // Update the position of the rain
  rain_->UpdatePosition();

  // FPS counter - also determine delta time
  long long current_frame = glutGet(GLUT_ELAPSED_TIME);
  frames_count_ += 1;
  if ((current_frame - frames_past_) > 1000) {
    const int fps = frames_count_ * 1000.0f / (current_frame - frames_past_);
      std::cout << "FPS: " << frames_count_ << std::endl;
    frames_count_ = 0;
    frames_past_ = current_frame;

    // Work out average miliseconds per tick
    const GLfloat delta_time = 1.0f/fps * 1000.0f;
    if (abs(delta_time_ - delta_time) < 5)
      delta_time_ = delta_time;
    // printf("dt = %f\n",delta_time_);
  }

  // Update Sun/Moon position
  sun_.Update();

  // Send time for water
  water_->SendTime(current_frame);
  terrain_->GenerationTick();

  // printf("mid = (%f,%f,%f)\n",left_lane_midpoint_.x,left_lane_midpoint_.y,left_lane_midpoint_.z);
  // printf("car = (%f,%f,%f)\n",car_->translation().x,car_->translation().y,car_->translation().z);
  if (!collision_controller_.is_collision()) {
    UpdatePhysics();
    game_state_ = collision_controller_.UpdateCollisions(car_, terrain_, &camera_, &road_sign_, game_state_);
  } else {
    // TODO add car off road shaking
  }
  car_->UpdateModelMatrix();

  UpdateCamera();

  if (game_state_ == kCrashingFall) {
    // delta_time_ /= 5; //slowmo
    if(playSound)
      system("aplay ./sounds/metal_crash.wav -q &");
    playSound = 0;
    game_state_ = collision_controller_.CrashAnimationFall(&camera_, terrain_, car_, delta_time_, is_key_pressed_hash_);
    return;
  }
  if (game_state_ == kCrashingCliff) {
    // delta_time_ /= 5; //slowmo
    if(playSound)
      system("aplay ./sounds/metal_crash.wav -q &");
    playSound = 0;
    game_state_ = collision_controller_.CrashAnimationCliff(&camera_, terrain_, car_, delta_time_, is_key_pressed_hash_);
    return;
  }

  if (is_key_pressed_hash_.at('w') || is_key_pressed_hash_.at('s')
      || is_key_pressed_hash_.at('a') || is_key_pressed_hash_.at('d')) {
    game_state_ = kStart;
    playSound = 1;
  }
}

// The controllers camera update tick
//   Uses car position (for chase and 1st person view)
//   and checks keypresses for freeview
//   @warn should be called before car movement
void Controller::UpdateCamera() {
  // CAMERA CONTROLS
  // Freeview movement
  camera_.Movement(delta_time_, is_key_pressed_hash_);
  // Point at car
  camera_.UpdateCarTick(car_);
  // Update camera lookAt
  camera_.UpdateCamera();

}

// The controllers physics update tick
//   Checks keypresses and calculates acceleration
void Controller::UpdatePhysics() {

  if (game_state_ == kStart) {
    // Sets variables required for camera
    //  i.e. camera has access to car in UpdateCarTick(car_)
    car_->ControllerMovementTick(delta_time_, is_key_pressed_hash_);
  }

  if (game_state_ == kAutoDrive) {
    collision_controller_.AutoDrive(car_, delta_time_);
  }

}
<commit_msg>capped delta time<commit_after>#include "controller.h"

// Constructor
//   Allows for Verbose Debugging Mode
//   @param bool debug_flag, true will enable verbose debugging
//   @warn assert will end program prematurely
//   @note axis is rendered in debugging mode
Controller::Controller(const int window_width, const int window_height, const bool debug_flag) :
  // Object construction
  renderer_(Renderer(debug_flag)),
  shaders_(renderer_.shaders()),
  camera_(Camera(shaders_, window_width, window_height)),
  sun_(Sun(camera(), debug_flag)),
  light_controller_(new LightController()),
  collision_controller_(CollisionController()),
  terrain_(new Terrain(shaders_->LightMappedGeneric)),
  road_sign_(RoadSign(shaders_, terrain_)),
  car_(AddObject(shaders_->LightMappedGeneric, "models/Pick-up_Truck/pickup_wind_alpha.obj")),
  // State and var defaults
  game_state_(kAutoDrive), light_pos_(glm::vec4(0,0,0,0)),
  frames_past_(0), frames_count_(0), delta_time_(18), is_debugging_(debug_flag) {

    is_key_pressed_hash_.reserve(256);
    is_key_pressed_hash_.resize(256);
    playSound = 1;

    rain_ = new Rain(shaders_->RainGeneric, debug_flag);
    water_ = new Water(shaders_->WaterGeneric);
    skybox_ = new Skybox(shaders_->SkyboxGeneric);

  // Add starting models
  // AddModel(shaders_->LightMappedGeneric, "models/Pick-up_Truck/pickup.obj", true);
  // AddModel(shaders_->LightMappedGeneric, "models/Car/car-n.obj", true);
  // AddModel(shaders_->LightMappedGeneric, "models/Signs_OBJ/working/curve_left.obj");
  // AddModel(shaders_->LightMappedGeneric, "models/Signs_OBJ/working/curve_right.obj");
  // AddModel(shaders_->LightMappedGeneric, "models/Signs_OBJ/working/60.obj");

}

// Adds a model to the member vector
//   @param shader, a shader class holding shader to use and uniforms
//   @param model_filename, a string containing the path of the .obj file
//   @warn the model is created on the heap and memory must be freed afterwards
Object * Controller::AddObject(const Shader &shader, const std::string &model_filename) {
  Object * object = new Model(shader, model_filename,
      glm::vec3(0.95f, 0.55f, 35.0f),     // Translation  move behind first tile (i.e. start on 2nd tile)
      glm::vec3(0.0f, 20.0f, 0.0f),       // Rotation
      glm::vec3(0.4f,  0.4f*1.6f, 0.4f),  // Scale
      60, false); // starting speed and debugging mode

  return object;
}

// Renders all models in the vector member
//   Should be called in the render loop
void Controller::Draw() {
  // Draw to shadow buffer
  glBindFramebuffer(GL_FRAMEBUFFER, renderer_.fbo()->FrameBufferShadows);
  glClear(GL_DEPTH_BUFFER_BIT);
  glViewport(0, 0, renderer_.fbo()->textureX, renderer_.fbo()->textureY);

  // Car with physics
  renderer_.RenderDepthBuffer(car_, sun_);
  // Road-signs
  const std::vector<Object*> signs = road_sign_.signs();
  const std::vector<int> active_signs = road_sign_.active_signs();

  // Unfortunately this does not work
  // for (unsigned int x = 0; x < signs.size(); ++x) {
  //   // if (active_signs[x] >= 0) // no point
  //   renderer_.RenderDepthBuffer(signs[x], sun_);
  // }
  // Terrain
  renderer_.RenderDepthBuffer(terrain_, sun_);

  // Draw to screen
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
  // Bind shadow map texture
  glBindTexture(GL_TEXTURE_2D, renderer_.fbo()->DepthTexture);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glViewport(0, 0, camera_.width(), camera_.height());

  // Ordering of renderering is very important due to transparency
  renderer_.RenderSkybox(skybox_, camera_);
  // Water
  renderer_.RenderWater(water_, car_, skybox_, camera_);
  // Terrain
  renderer_.Render(terrain_, camera_, sun_);
  // Road-signs
  for (unsigned int x = 0; x < signs.size(); ++x) {
    // if (active_signs[x] >= 0) // no point
    renderer_.Render(signs[x], camera_, sun_);
  }
  if (camera_.state() == Camera::kFirstPerson) {
    // Rain (particles)
    if (sun_.time_of_day() != 12)
      rain_->Render(camera_, car_, skybox_);
  // Car with physics
  renderer_.Render(car_, camera_, sun_);
  } else {
    // Car with physics
    renderer_.Render(car_, camera_, sun_);
    // Rain (particles)
    if (sun_.time_of_day() != 12)
      rain_->Render(camera_, car_, skybox_);
  }

  // Axis only renders in debugging mode
  renderer_.RenderAxis(camera_);
}

// Assumes SetupLighting() has been called, only updates essential light properties
void Controller::PositionLights() {
  glm::mat4 view_matrix = camera_.view_matrix();
  glm::mat4 car_mv_matrix = view_matrix * car_->model_matrix();
  // glm::mat3 norm_matrix = glm::mat3(view_matrix);

  DirectionalLight dirLight;

  dirLight.DiffuseIntensity = glm::vec3(1.00f, 1.00f, 1.00f);
  dirLight.AmbientIntensity = glm::vec3(0.50f, 0.50f, 0.50f);
  dirLight.SpecularIntensity = glm::vec3(0.35f, 0.35f, 0.40f);
  dirLight.DiffuseIntensity *= sun_.LightIntensityMultiplier();
  dirLight.AmbientIntensity *= sun_.LightIntensityMultiplier();
  // dirLight.SpecularIntensity *= 1.0f - sun_.LightIntensityMultiplier();
  // if (!sun_.IsDay()) {
  //   dirLight.SpecularIntensity.x *= 1.0f - sun_.LightIntensityMultiplier();
  //   dirLight.SpecularIntensity.y *= 1.0f - sun_.LightIntensityMultiplier();
  // }
  dirLight.Direction =  sun_.sun_direction();

  // Point lights
  std::vector<PointLight> pointLights;
  // Main car brake lights
  for (unsigned int i = 0; i < 2; i++) {
    glm::mat4 brakeLightTranslation = glm::translate(glm::mat4(1.0f), glm::vec3(-0.85f + i * 1.7f, 0.0f, -3.3f));

    PointLight brakeLight;
    brakeLight.DiffuseIntensity = glm::vec3(1.0f, 0.0f, 0.0f);
    brakeLight.Position = glm::vec3(car_mv_matrix * brakeLightTranslation * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
    brakeLight.Attenuation.Constant = 0.001f;
    brakeLight.Attenuation.Linear = 2.0f;
    brakeLight.Attenuation.Exp = 3.0f;

    if (is_key_pressed_hash_.at('s')) {
      brakeLight.Attenuation.Constant = 0.00001f;
      brakeLight.Attenuation.Linear = 0.5f;
      brakeLight.Attenuation.Exp = 3.0f;
    }

    pointLights.push_back(brakeLight);
  }

  // Spot lights
  std::vector<SpotLight> spotLights;
  // Main car headlights
  for (unsigned int i = 0; i < 2; i++) {
    glm::mat4 headlightTranslation = glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f + i * 1.0f, 0.0f, 1.45f));
    glm::mat3 headlightNormMatrix = glm::mat3(car_mv_matrix);

    SpotLight headlight;
    headlight.DiffuseIntensity = glm::vec3(1.0f, 1.0f, 1.0f);
    headlight.SpecularIntensity = glm::vec3(0.1f, 0.1f, 0.1f);
    headlight.Position = glm::vec3(car_mv_matrix * headlightTranslation * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
    headlight.Direction = headlightNormMatrix * glm::vec3(0.0f, -0.3f, 1.0f);
    headlight.CosineCutoff = cos(DEG2RAD(30.0f));
    headlight.Attenuation.Constant = 0.3f;
    headlight.Attenuation.Linear = 0.01f;
    headlight.Attenuation.Exp = 0.01f;

    if (is_key_pressed_hash_.at('r')) {
      headlight.DiffuseIntensity = glm::vec3(0.0f, 0.0f, 0.0f);
      headlight.SpecularIntensity = glm::vec3(0.0f, 0.0f, 0.0f);
    }

    spotLights.push_back(headlight);
  }

  light_controller_->SetDirectionalLight(car_->shader()->Id, dirLight);
  light_controller_->SetSpotLights(water_->shader().Id, spotLights.size(), &spotLights[0]);
  light_controller_->SetDirectionalLight(water_->shader().Id, dirLight);

  light_controller_->SetPointLights(car_->shader()->Id, pointLights.size(), &pointLights[0]);
  light_controller_->SetSpotLights(car_->shader()->Id, spotLights.size(), &spotLights[0]);
}

// The main control tick
//   Controls everything: camera, inputs, physics, collisions
void Controller::UpdateGame() {
  // Lights need to be transformed with view/normal matrix
  PositionLights();
  // Update the position of the rain
  rain_->UpdatePosition();

  // FPS counter - also determine delta time
  long long current_frame = glutGet(GLUT_ELAPSED_TIME);
  frames_count_ += 1;
  if ((current_frame - frames_past_) > 1000) {
    const int fps = frames_count_ * 1000.0f / (current_frame - frames_past_);
      std::cout << "FPS: " << frames_count_ << std::endl;
    frames_count_ = 0;
    frames_past_ = current_frame;

    // Work out average miliseconds per tick
    const GLfloat delta_time = 1.0f/fps * 1000.0f;
    if (abs(delta_time_ - delta_time) < 5) // Dont allow too high fluc
      delta_time_ = delta_time;
    if (delta_time_ > 20) // Cap at 50 fps delta (will run in slowmo on less fps)
      delta_time_ = 20;
    // printf("dt = %f\n",delta_time_);
  }

  // Update Sun/Moon position
  sun_.Update();

  // Send time for water
  water_->SendTime(current_frame);
  terrain_->GenerationTick();

  // printf("mid = (%f,%f,%f)\n",left_lane_midpoint_.x,left_lane_midpoint_.y,left_lane_midpoint_.z);
  // printf("car = (%f,%f,%f)\n",car_->translation().x,car_->translation().y,car_->translation().z);
  if (!collision_controller_.is_collision()) {
    UpdatePhysics();
    game_state_ = collision_controller_.UpdateCollisions(car_, terrain_, &camera_, &road_sign_, game_state_);
  } else {
    // TODO add car off road shaking
  }
  car_->UpdateModelMatrix();

  UpdateCamera();

  if (game_state_ == kCrashingFall) {
    // delta_time_ /= 5; //slowmo
    if(playSound)
      system("aplay ./sounds/metal_crash.wav -q &");
    playSound = 0;
    game_state_ = collision_controller_.CrashAnimationFall(&camera_, terrain_, car_, delta_time_, is_key_pressed_hash_);
    return;
  }
  if (game_state_ == kCrashingCliff) {
    // delta_time_ /= 5; //slowmo
    if(playSound)
      system("aplay ./sounds/metal_crash.wav -q &");
    playSound = 0;
    game_state_ = collision_controller_.CrashAnimationCliff(&camera_, terrain_, car_, delta_time_, is_key_pressed_hash_);
    return;
  }

  if (is_key_pressed_hash_.at('w') || is_key_pressed_hash_.at('s')
      || is_key_pressed_hash_.at('a') || is_key_pressed_hash_.at('d')) {
    game_state_ = kStart;
    playSound = 1;
  }
}

// The controllers camera update tick
//   Uses car position (for chase and 1st person view)
//   and checks keypresses for freeview
//   @warn should be called before car movement
void Controller::UpdateCamera() {
  // CAMERA CONTROLS
  // Freeview movement
  camera_.Movement(delta_time_, is_key_pressed_hash_);
  // Point at car
  camera_.UpdateCarTick(car_);
  // Update camera lookAt
  camera_.UpdateCamera();

}

// The controllers physics update tick
//   Checks keypresses and calculates acceleration
void Controller::UpdatePhysics() {

  if (game_state_ == kStart) {
    // Sets variables required for camera
    //  i.e. camera has access to car in UpdateCarTick(car_)
    car_->ControllerMovementTick(delta_time_, is_key_pressed_hash_);
  }

  if (game_state_ == kAutoDrive) {
    collision_controller_.AutoDrive(car_, delta_time_);
  }

}
<|endoftext|>


<commit_before>#include "StdAfx.h"
#include "OrfDecoder.h"
#if defined(__unix__) || defined(__APPLE__)
#include <stdlib.h>
#endif
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014-2015 Pedro Côrte-Real

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

OrfDecoder::OrfDecoder(TiffIFD *rootIFD, FileMap* file):
    RawDecoder(file), mRootIFD(rootIFD) {
      decoderVersion = 3;
}

OrfDecoder::~OrfDecoder(void) {
  if (mRootIFD)
    delete mRootIFD;
  mRootIFD = NULL;
}

RawImage OrfDecoder::decodeRawInternal() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(STRIPOFFSETS);

  if (data.empty())
    ThrowRDE("ORF Decoder: No image data found");

  TiffIFD* raw = data[0];

  int compression = raw->getEntry(COMPRESSION)->getInt();
  if (1 != compression)
    ThrowRDE("ORF Decoder: Unsupported compression");

  TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
  TiffEntry *counts = raw->getEntry(STRIPBYTECOUNTS);

  if (counts->count != offsets->count)
    ThrowRDE("ORF Decoder: Byte count number does not match strip size: count:%u, strips:%u ", counts->count, offsets->count);

  uint32 off = raw->getEntry(STRIPOFFSETS)->getInt();
  uint32 size = 0;
  for (uint32 i=0; i < counts->count; i++)
    size += counts->getInt(i);

  if (!mFile->isValid(off, size))
    ThrowRDE("ORF Decoder: Truncated file");

  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();

  // We add 3 bytes slack, since the bitpump might be a few bytes ahead.
  ByteStream input(mFile, off, size+3);

  try {
    if (offsets->count != 1 || (hints.find(string("force_uncompressed")) != hints.end()))
      decodeUncompressed(input, width, height, size, raw->endian);
    else
      decodeCompressed(input, width, height);
  } catch (IOException &e) {
     mRaw->setError(e.what());
  }

  return mRaw;
}

void OrfDecoder::decodeUncompressed(ByteStream& s, uint32 w, uint32 h, uint32 size, Endianness endian) {
  if ((hints.find(string("packed_with_control")) != hints.end()))
    Decode12BitRawWithControl(s, w, h);
  else if ((hints.find(string("jpeg32_bitorder")) != hints.end())) {
    iPoint2D size(w, h),pos(0,0);
    readUncompressedRaw(s, size, pos, w*12/8, 12, BitOrder_Jpeg32);
  } else if (size >= w*h*2) { // We're in an unpacked raw
    if (endian == little)
      Decode12BitRawUnpacked(s, w, h);
    else
      Decode12BitRawBEunpackedLeftAligned(s, w, h);
  } else if (size >= w*h*3/2) { // We're in one of those weird interlaced packed raws
      Decode12BitRawBEInterlaced(s, w, h);
  } else {
    ThrowRDE("ORF Decoder: Don't know how to handle the encoding in this file\n");
  }
}

/* This is probably the slowest decoder of them all.
 * I cannot see any way to effectively speed up the prediction
 * phase, which is by far the slowest part of this algorithm.
 * Also there is no way to multithread this code, since prediction
 * is based on the output of all previous pixel (bar the first four)
 */

void OrfDecoder::decodeCompressed(ByteStream& s, uint32 w, uint32 h) {
  int nbits, sign, low, high, i, left0, nw0, left1, nw1;
  int acarry0[3], acarry1[3], pred, diff;

  uchar8* data = mRaw->getData();
  int pitch = mRaw->pitch;

  /* Build a table to quickly look up "high" value */
  char bittable[4096];
  for (i = 0; i < 4096; i++) {
    int b = i;
    for (high = 0; high < 12; high++)
      if ((b>>(11-high))&1)
        break;
      bittable[i] = min(12,high);
  }
  left0 = nw0 = left1 = nw1 = 0;

  s.skipBytes(7);
  BitPumpMSB bits(&s);

  for (uint32 y = 0; y < h; y++) {
    memset(acarry0, 0, sizeof acarry0);
    memset(acarry1, 0, sizeof acarry1);
    ushort16* dest = (ushort16*) & data[y*pitch];
    bool y_border = y < 2;
    bool border = TRUE;
    for (uint32 x = 0; x < w; x++) {
      bits.checkPos();
      bits.fill();
      i = 2 * (acarry0[2] < 3);
      for (nbits = 2 + i; (ushort16) acarry0[0] >> (nbits + i); nbits++);

      int b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low  = (b >> 12) & 3;
      high = bittable[b&4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else {
        bits.skipBitsNoFill(high + 1 + 3);
      }

      acarry0[0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry0[0] ^ sign) + acarry0[1];
      acarry0[1] = (diff * 3 + acarry0[1]) >> 5;
      acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else if (y_border)
          pred = left0;
        else {
          pred = dest[-pitch+((int)x)];
          nw0 = pred;
        }
        dest[x] = pred + ((diff << 2) | low);
        // Set predictor
        left0 = dest[x];
      } else {
        // Have local variables for values used several tiles
        // (having a "ushort16 *dst_up" that caches dest[-pitch+((int)x)] is actually slower, probably stack spill or aliasing)
        int up  = dest[-pitch+((int)x)];
        int leftMinusNw = left0 - nw0;
        int upMinusNw = up - nw0;
        // Check if sign is different, and one is not zero
        if (leftMinusNw * upMinusNw < 0) {
          if (other_abs(leftMinusNw) > 32 || other_abs(upMinusNw) > 32)
            pred = left0 + upMinusNw;
          else
            pred = (left0 + up) >> 1;
        } else
          pred = other_abs(leftMinusNw) > other_abs(upMinusNw) ? left0 : up;

        dest[x] = pred + ((diff << 2) | low);
        // Set predictors
        left0 = dest[x];
        nw0 = up;
      }

      // ODD PIXELS
      x += 1;
      bits.fill();
      i = 2 * (acarry1[2] < 3);
      for (nbits = 2 + i; (ushort16) acarry1[0] >> (nbits + i); nbits++);
      b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low  = (b >> 12) & 3;
      high = bittable[b&4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else {
        bits.skipBitsNoFill(high + 1 + 3);
      }

      acarry1[0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry1[0] ^ sign) + acarry1[1];
      acarry1[1] = (diff * 3 + acarry1[1]) >> 5;
      acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else if (y_border)
          pred = left1;
        else {
          pred = dest[-pitch+((int)x)];
          nw1 = pred;
        }
        dest[x] = left1 = pred + ((diff << 2) | low);
      } else {
        int up  = dest[-pitch+((int)x)];
        int leftMinusNw = left1 - nw1;
        int upMinusNw = up - nw1;

        // Check if sign is different, and one is not zero
        if (leftMinusNw * upMinusNw < 0) {
          if (other_abs(leftMinusNw) > 32 || other_abs(upMinusNw) > 32)
            pred = left1 + upMinusNw;
          else
            pred = (left1 + up) >> 1;
        } else
          pred = other_abs(leftMinusNw) > other_abs(upMinusNw) ? left1 : up;

        dest[x] = left1 = pred + ((diff << 2) | low);
        nw1 = up;
      }
      border = y_border;
    }
  }
}

void OrfDecoder::checkSupportInternal(CameraMetaData *meta) {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);
  if (data.empty())
    ThrowRDE("ORF Support check: Model name found");
  if (!data[0]->hasEntry(MAKE))
    ThrowRDE("ORF Support: Make name not found");
  string make = data[0]->getEntry(MAKE)->getString();
  string model = data[0]->getEntry(MODEL)->getString();
  this->checkCameraSupported(meta, make, model, "");
}

void OrfDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
  int iso = 0;
  mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN, CFA_BLUE);
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("ORF Meta Decoder: Model name found");

  string make = data[0]->getEntry(MAKE)->getString();
  string model = data[0]->getEntry(MODEL)->getString();

  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getInt();

  setMetaData(meta, make, model, "", iso);

  if (mRootIFD->hasEntryRecursive(OLYMPUSREDMULTIPLIER) &&
      mRootIFD->hasEntryRecursive(OLYMPUSBLUEMULTIPLIER)) {
    mRaw->metadata.wbCoeffs[0] = (float) mRootIFD->getEntryRecursive(OLYMPUSREDMULTIPLIER)->getShort();
    mRaw->metadata.wbCoeffs[1] = 256.0f;
    mRaw->metadata.wbCoeffs[2] = (float) mRootIFD->getEntryRecursive(OLYMPUSBLUEMULTIPLIER)->getShort();
  } else {
    // Newer cameras process the Image Processing SubIFD in the makernote
    if(mRootIFD->hasEntryRecursive(OLYMPUSIMAGEPROCESSING)) {
      TiffEntry *img_entry = mRootIFD->getEntryRecursive(OLYMPUSIMAGEPROCESSING);
      uint32 offset = img_entry->getInt() + img_entry->parent_offset - 12;
      TiffIFD *image_processing = NULL;
      try {
        if (mRootIFD->endian == getHostEndianness())
          image_processing = new TiffIFD(mFile, offset);
        else
          image_processing = new TiffIFDBE(mFile, offset);

        // Get the WB
        if(image_processing->hasEntry((TiffTag) 0x0100)) {
          TiffEntry *wb = image_processing->getEntry((TiffTag) 0x0100);
          if (wb->count == 4) {
            wb->parent_offset = img_entry->parent_offset - 12;
            wb->offsetFromParent();
          }
          if (wb->count == 2 || wb->count == 4) {
            mRaw->metadata.wbCoeffs[0] = wb->getFloat(0);
            mRaw->metadata.wbCoeffs[1] = 256.0f;
            mRaw->metadata.wbCoeffs[2] = wb->getFloat(1);
          }
        }

        // Get the black levels
        if(image_processing->hasEntry((TiffTag) 0x0600)) {
          TiffEntry *blackEntry = image_processing->getEntry((TiffTag) 0x0600);
          // Order is assumed to be RGGB
          if (blackEntry->count == 4) {
            blackEntry->parent_offset = img_entry->parent_offset - 12;
            blackEntry->offsetFromParent();
            for (int i = 0; i < 4; i++) {
              if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_RED)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(0);
              else if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_BLUE)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(3);
              else if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_GREEN && i<2)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(1);
              else if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_GREEN)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(2);
            }
            // Adjust whitelevel based on the read black (we assume the dynamic range is the same)
            mRaw->whitePoint -= (mRaw->blackLevel - mRaw->blackLevelSeparate[0]);
          }
        }
      } catch(TiffParserException e) {
        mRaw->setError(e.what());
      }

      if (image_processing)
        delete image_processing;
    }
  }
}

} // namespace RawSpeed
<commit_msg>Fix for gcc6 compilation<commit_after>#include "StdAfx.h"
#include "OrfDecoder.h"
#if defined(__unix__) || defined(__APPLE__)
#include <stdlib.h>
#endif
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014-2015 Pedro Côrte-Real

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

OrfDecoder::OrfDecoder(TiffIFD *rootIFD, FileMap* file):
    RawDecoder(file), mRootIFD(rootIFD) {
      decoderVersion = 3;
}

OrfDecoder::~OrfDecoder(void) {
  if (mRootIFD)
    delete mRootIFD;
  mRootIFD = NULL;
}

RawImage OrfDecoder::decodeRawInternal() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(STRIPOFFSETS);

  if (data.empty())
    ThrowRDE("ORF Decoder: No image data found");

  TiffIFD* raw = data[0];

  int compression = raw->getEntry(COMPRESSION)->getInt();
  if (1 != compression)
    ThrowRDE("ORF Decoder: Unsupported compression");

  TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
  TiffEntry *counts = raw->getEntry(STRIPBYTECOUNTS);

  if (counts->count != offsets->count)
    ThrowRDE("ORF Decoder: Byte count number does not match strip size: count:%u, strips:%u ", counts->count, offsets->count);

  uint32 off = raw->getEntry(STRIPOFFSETS)->getInt();
  uint32 size = 0;
  for (uint32 i=0; i < counts->count; i++)
    size += counts->getInt(i);

  if (!mFile->isValid(off, size))
    ThrowRDE("ORF Decoder: Truncated file");

  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();

  // We add 3 bytes slack, since the bitpump might be a few bytes ahead.
  ByteStream input(mFile, off, size+3);

  try {
    if (offsets->count != 1 || (hints.find(string("force_uncompressed")) != hints.end()))
      decodeUncompressed(input, width, height, size, raw->endian);
    else
      decodeCompressed(input, width, height);
  } catch (IOException &e) {
     mRaw->setError(e.what());
  }

  return mRaw;
}

void OrfDecoder::decodeUncompressed(ByteStream& s, uint32 w, uint32 h, uint32 size, Endianness endian) {
  if ((hints.find(string("packed_with_control")) != hints.end()))
    Decode12BitRawWithControl(s, w, h);
  else if ((hints.find(string("jpeg32_bitorder")) != hints.end())) {
    iPoint2D size(w, h),pos(0,0);
    readUncompressedRaw(s, size, pos, w*12/8, 12, BitOrder_Jpeg32);
  } else if (size >= w*h*2) { // We're in an unpacked raw
    if (endian == little)
      Decode12BitRawUnpacked(s, w, h);
    else
      Decode12BitRawBEunpackedLeftAligned(s, w, h);
  } else if (size >= w*h*3/2) { // We're in one of those weird interlaced packed raws
      Decode12BitRawBEInterlaced(s, w, h);
  } else {
    ThrowRDE("ORF Decoder: Don't know how to handle the encoding in this file\n");
  }
}

/* This is probably the slowest decoder of them all.
 * I cannot see any way to effectively speed up the prediction
 * phase, which is by far the slowest part of this algorithm.
 * Also there is no way to multithread this code, since prediction
 * is based on the output of all previous pixel (bar the first four)
 */

void OrfDecoder::decodeCompressed(ByteStream& s, uint32 w, uint32 h) {
  int nbits, sign, low, high, i, left0, nw0, left1, nw1;
  int acarry0[3], acarry1[3], pred, diff;

  uchar8* data = mRaw->getData();
  int pitch = mRaw->pitch;

  /* Build a table to quickly look up "high" value */
  char bittable[4096];
  for (i = 0; i < 4096; i++) {
    int b = i;
    for (high = 0; high < 12; high++)
      if ((b>>(11-high))&1)
        break;
    bittable[i] = min(12,high);
  }
  left0 = nw0 = left1 = nw1 = 0;

  s.skipBytes(7);
  BitPumpMSB bits(&s);

  for (uint32 y = 0; y < h; y++) {
    memset(acarry0, 0, sizeof acarry0);
    memset(acarry1, 0, sizeof acarry1);
    ushort16* dest = (ushort16*) & data[y*pitch];
    bool y_border = y < 2;
    bool border = TRUE;
    for (uint32 x = 0; x < w; x++) {
      bits.checkPos();
      bits.fill();
      i = 2 * (acarry0[2] < 3);
      for (nbits = 2 + i; (ushort16) acarry0[0] >> (nbits + i); nbits++);

      int b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low  = (b >> 12) & 3;
      high = bittable[b&4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else {
        bits.skipBitsNoFill(high + 1 + 3);
      }

      acarry0[0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry0[0] ^ sign) + acarry0[1];
      acarry0[1] = (diff * 3 + acarry0[1]) >> 5;
      acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else if (y_border)
          pred = left0;
        else {
          pred = dest[-pitch+((int)x)];
          nw0 = pred;
        }
        dest[x] = pred + ((diff << 2) | low);
        // Set predictor
        left0 = dest[x];
      } else {
        // Have local variables for values used several tiles
        // (having a "ushort16 *dst_up" that caches dest[-pitch+((int)x)] is actually slower, probably stack spill or aliasing)
        int up  = dest[-pitch+((int)x)];
        int leftMinusNw = left0 - nw0;
        int upMinusNw = up - nw0;
        // Check if sign is different, and one is not zero
        if (leftMinusNw * upMinusNw < 0) {
          if (other_abs(leftMinusNw) > 32 || other_abs(upMinusNw) > 32)
            pred = left0 + upMinusNw;
          else
            pred = (left0 + up) >> 1;
        } else
          pred = other_abs(leftMinusNw) > other_abs(upMinusNw) ? left0 : up;

        dest[x] = pred + ((diff << 2) | low);
        // Set predictors
        left0 = dest[x];
        nw0 = up;
      }

      // ODD PIXELS
      x += 1;
      bits.fill();
      i = 2 * (acarry1[2] < 3);
      for (nbits = 2 + i; (ushort16) acarry1[0] >> (nbits + i); nbits++);
      b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low  = (b >> 12) & 3;
      high = bittable[b&4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else {
        bits.skipBitsNoFill(high + 1 + 3);
      }

      acarry1[0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry1[0] ^ sign) + acarry1[1];
      acarry1[1] = (diff * 3 + acarry1[1]) >> 5;
      acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else if (y_border)
          pred = left1;
        else {
          pred = dest[-pitch+((int)x)];
          nw1 = pred;
        }
        dest[x] = left1 = pred + ((diff << 2) | low);
      } else {
        int up  = dest[-pitch+((int)x)];
        int leftMinusNw = left1 - nw1;
        int upMinusNw = up - nw1;

        // Check if sign is different, and one is not zero
        if (leftMinusNw * upMinusNw < 0) {
          if (other_abs(leftMinusNw) > 32 || other_abs(upMinusNw) > 32)
            pred = left1 + upMinusNw;
          else
            pred = (left1 + up) >> 1;
        } else
          pred = other_abs(leftMinusNw) > other_abs(upMinusNw) ? left1 : up;

        dest[x] = left1 = pred + ((diff << 2) | low);
        nw1 = up;
      }
      border = y_border;
    }
  }
}

void OrfDecoder::checkSupportInternal(CameraMetaData *meta) {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);
  if (data.empty())
    ThrowRDE("ORF Support check: Model name found");
  if (!data[0]->hasEntry(MAKE))
    ThrowRDE("ORF Support: Make name not found");
  string make = data[0]->getEntry(MAKE)->getString();
  string model = data[0]->getEntry(MODEL)->getString();
  this->checkCameraSupported(meta, make, model, "");
}

void OrfDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
  int iso = 0;
  mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN, CFA_BLUE);
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("ORF Meta Decoder: Model name found");

  string make = data[0]->getEntry(MAKE)->getString();
  string model = data[0]->getEntry(MODEL)->getString();

  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getInt();

  setMetaData(meta, make, model, "", iso);

  if (mRootIFD->hasEntryRecursive(OLYMPUSREDMULTIPLIER) &&
      mRootIFD->hasEntryRecursive(OLYMPUSBLUEMULTIPLIER)) {
    mRaw->metadata.wbCoeffs[0] = (float) mRootIFD->getEntryRecursive(OLYMPUSREDMULTIPLIER)->getShort();
    mRaw->metadata.wbCoeffs[1] = 256.0f;
    mRaw->metadata.wbCoeffs[2] = (float) mRootIFD->getEntryRecursive(OLYMPUSBLUEMULTIPLIER)->getShort();
  } else {
    // Newer cameras process the Image Processing SubIFD in the makernote
    if(mRootIFD->hasEntryRecursive(OLYMPUSIMAGEPROCESSING)) {
      TiffEntry *img_entry = mRootIFD->getEntryRecursive(OLYMPUSIMAGEPROCESSING);
      uint32 offset = img_entry->getInt() + img_entry->parent_offset - 12;
      TiffIFD *image_processing = NULL;
      try {
        if (mRootIFD->endian == getHostEndianness())
          image_processing = new TiffIFD(mFile, offset);
        else
          image_processing = new TiffIFDBE(mFile, offset);

        // Get the WB
        if(image_processing->hasEntry((TiffTag) 0x0100)) {
          TiffEntry *wb = image_processing->getEntry((TiffTag) 0x0100);
          if (wb->count == 4) {
            wb->parent_offset = img_entry->parent_offset - 12;
            wb->offsetFromParent();
          }
          if (wb->count == 2 || wb->count == 4) {
            mRaw->metadata.wbCoeffs[0] = wb->getFloat(0);
            mRaw->metadata.wbCoeffs[1] = 256.0f;
            mRaw->metadata.wbCoeffs[2] = wb->getFloat(1);
          }
        }

        // Get the black levels
        if(image_processing->hasEntry((TiffTag) 0x0600)) {
          TiffEntry *blackEntry = image_processing->getEntry((TiffTag) 0x0600);
          // Order is assumed to be RGGB
          if (blackEntry->count == 4) {
            blackEntry->parent_offset = img_entry->parent_offset - 12;
            blackEntry->offsetFromParent();
            for (int i = 0; i < 4; i++) {
              if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_RED)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(0);
              else if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_BLUE)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(3);
              else if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_GREEN && i<2)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(1);
              else if (mRaw->cfa.getColorAt(i&1, i>>1) == CFA_GREEN)
                mRaw->blackLevelSeparate[i] = blackEntry->getShort(2);
            }
            // Adjust whitelevel based on the read black (we assume the dynamic range is the same)
            mRaw->whitePoint -= (mRaw->blackLevel - mRaw->blackLevelSeparate[0]);
          }
        }
      } catch(TiffParserException e) {
        mRaw->setError(e.what());
      }

      if (image_processing)
        delete image_processing;
    }
  }
}

} // namespace RawSpeed
<|endoftext|>