<commit_before>#ifndef _DWARFPP_INTERNAL_HH_
#define _DWARFPP_INTERNAL_HH_

#include "dwarf++.hh"

#include <stdexcept>
#include <type_traits>
#include <unordered_map>
#include <vector>

DWARFPP_BEGIN_NAMESPACE

template<typename T>
std::string
to_hex(T v)
{
        static_assert(std::is_integral<T>::value,
                "to_hex applied to non-integral type");
        if (v == 0)
                return std::string("0");
        char buf[sizeof(T)*2 + 1];
        char *pos = &buf[sizeof(buf)-1];
        *pos-- = '\0';
        while (v && pos >= buf) {
                int digit = v & 0xf;
                if (digit < 10)
                        *pos = '0' + digit;
                else
                        *pos = 'a' + (digit - 10);
                pos--;
                v >>= 4;
        }
        return std::string(pos + 1);
}

enum class format
{
        unknown,
        dwarf32,
        dwarf64
};

/**
 * A single DWARF section or a slice of a section.  This also tracks
 * dynamic information necessary to decode values in this section.
 */
struct section
{
        section_type type;
        const char *begin, *end;
        const format fmt;
        unsigned addr_size;

        section(section_type type, const void *begin,
                section_length length, format fmt = format::unknown,
                unsigned addr_size = 0)
                : type(type), begin((char*)begin), end((char*)begin + length),
                  fmt(fmt), addr_size(addr_size) { }

        section(const section &o) = default;

        std::shared_ptr<section> slice(section_offset start, section_length len,
                                       format fmt = format::unknown,
                                       unsigned addr_size = 0)
        {
                if (fmt == format::unknown)
                        fmt = this->fmt;
                if (addr_size == 0)
                        addr_size = this->addr_size;

                return std::make_shared<section>(
                        type, begin+start,
                        std::min(len, (section_length)(end-begin)),
                        fmt, addr_size);
        }
};

/**
 * A cursor pointing into a DWARF section.  Provides deserialization
 * operations and bounds checking.
 */
struct cursor
{
        // XXX There's probably a lot of overhead to maintaining the
        // shared pointer to the section from this.  Perhaps the rule
        // should be that all objects keep the dwarf::impl alive
        // (directly or indirectly) and that keeps the loader alive,
        // so a cursor just needs a regular section*.

        std::shared_ptr<section> sec;
        const char *pos;

        cursor()
                : pos(nullptr) { }
        cursor(const std::shared_ptr<section> sec, section_offset offset = 0)
                : sec(sec), pos(sec->begin + offset) { }

        /**
         * Read a subsection.  The cursor must be at an initial
         * length.  After, the cursor will point just past the end of
         * the subsection.  The returned section has the appropriate
         * DWARF format and begins at the current location of the
         * cursor (so this is usually followed by a
         * skip_initial_length).
         */
        std::shared_ptr<section> subsection();
        std::int64_t sleb128();
        section_offset offset();
        void string(std::string &out);
        const char *cstr(size_t *size_out = nullptr);

        void
        ensure(section_offset bytes)
        {
                if ((section_offset)(sec->end - pos) < bytes || pos >= sec->end)
                        underflow();
        }

        template<typename T>
        T fixed()
        {
                ensure(sizeof(T));
                T val = *(T*)pos;
                pos += sizeof(T);
                return val;
        }

        std::uint64_t uleb128()
        {
                // Appendix C
                // XXX Pre-compute all two byte ULEB's
                std::uint64_t result = 0;
                int shift = 0;
                while (pos < sec->end) {
                        uint8_t byte = *(uint8_t*)(pos++);
                        result |= (uint64_t)(byte & 0x7f) << shift;
                        if ((byte & 0x80) == 0)
                                return result;
                        shift += 7;
                }
                underflow();
                return 0;
        }

        taddr address()
        {
                switch (sec->addr_size) {
                case 1:
                        return fixed<uint8_t>();
                case 2:
                        return fixed<uint16_t>();
                case 4:
                        return fixed<uint32_t>();
                case 8:
                        return fixed<uint64_t>();
                default:
                        throw std::runtime_error("address size " + std::to_string(sec->addr_size) + " not supported");
                }
        }

        void skip_initial_length();
        void skip_form(DW_FORM form);

        cursor &operator+=(section_offset offset)
        {
                pos += offset;
                return *this;
        }

        cursor operator+(section_offset offset) const
        {
                return cursor(sec, pos + offset);
        }

        bool operator<(const cursor &o) const
        {
                return pos < o.pos;
        }

        bool end() const
        {
                return pos >= sec->end;
        }

        bool valid() const
        {
                return !!pos;
        }

        section_offset get_section_offset() const
        {
                return pos - sec->begin;
        }

private:
        cursor(const std::shared_ptr<section> sec, const char *pos)
                : sec(sec), pos(pos) { }

        void underflow();
};

/**
 * An attribute specification in an abbrev.
 */
struct attribute_spec
{
        DW_AT name;
        DW_FORM form;

        // Computed information
        value::type type;

        attribute_spec(DW_AT name, DW_FORM form);
};

typedef std::uint64_t abbrev_code;

/**
 * An entry in .debug_abbrev.
 */
struct abbrev_entry
{
        abbrev_code code;
        DW_TAG tag;
        bool children;
        std::vector<attribute_spec> attributes;

        abbrev_entry() : code(0) { }

        bool read(cursor *cur);
};

/**
 * A section header in .debug_pubnames or .debug_pubtypes.
 */
struct name_unit
{
        uhalf version;
        section_offset debug_info_offset;
        section_length debug_info_length;
        // Cursor to the first name_entry in this unit.  This cursor's
        // section is limited to this unit.
        cursor entries;

        void read(cursor *cur)
        {
                // Section 7.19
                std::shared_ptr<section> subsec = cur->subsection();
                cursor sub(subsec);
                sub.skip_initial_length();
                version = sub.fixed<uhalf>();
                if (version != 2)
                        throw format_error("unknown name unit version " + std::to_string(version));
                debug_info_offset = sub.offset();
                debug_info_length = sub.offset();
                entries = sub;
        }
};

/**
 * An entry in a .debug_pubnames or .debug_pubtypes unit.
 */
struct name_entry
{
        section_offset offset;
        std::string name;

        void read(cursor *cur)
        {
                offset = cur->offset();
                cur->string(name);
        }
};

DWARFPP_END_NAMESPACE

#endif
<commit_msg>section::size method<commit_after>#ifndef _DWARFPP_INTERNAL_HH_
#define _DWARFPP_INTERNAL_HH_

#include "dwarf++.hh"

#include <stdexcept>
#include <type_traits>
#include <unordered_map>
#include <vector>

DWARFPP_BEGIN_NAMESPACE

template<typename T>
std::string
to_hex(T v)
{
        static_assert(std::is_integral<T>::value,
                "to_hex applied to non-integral type");
        if (v == 0)
                return std::string("0");
        char buf[sizeof(T)*2 + 1];
        char *pos = &buf[sizeof(buf)-1];
        *pos-- = '\0';
        while (v && pos >= buf) {
                int digit = v & 0xf;
                if (digit < 10)
                        *pos = '0' + digit;
                else
                        *pos = 'a' + (digit - 10);
                pos--;
                v >>= 4;
        }
        return std::string(pos + 1);
}

enum class format
{
        unknown,
        dwarf32,
        dwarf64
};

/**
 * A single DWARF section or a slice of a section.  This also tracks
 * dynamic information necessary to decode values in this section.
 */
struct section
{
        section_type type;
        const char *begin, *end;
        const format fmt;
        unsigned addr_size;

        section(section_type type, const void *begin,
                section_length length, format fmt = format::unknown,
                unsigned addr_size = 0)
                : type(type), begin((char*)begin), end((char*)begin + length),
                  fmt(fmt), addr_size(addr_size) { }

        section(const section &o) = default;

        std::shared_ptr<section> slice(section_offset start, section_length len,
                                       format fmt = format::unknown,
                                       unsigned addr_size = 0)
        {
                if (fmt == format::unknown)
                        fmt = this->fmt;
                if (addr_size == 0)
                        addr_size = this->addr_size;

                return std::make_shared<section>(
                        type, begin+start,
                        std::min(len, (section_length)(end-begin)),
                        fmt, addr_size);
        }

        size_t size() const
        {
                return end - begin;
        }
};

/**
 * A cursor pointing into a DWARF section.  Provides deserialization
 * operations and bounds checking.
 */
struct cursor
{
        // XXX There's probably a lot of overhead to maintaining the
        // shared pointer to the section from this.  Perhaps the rule
        // should be that all objects keep the dwarf::impl alive
        // (directly or indirectly) and that keeps the loader alive,
        // so a cursor just needs a regular section*.

        std::shared_ptr<section> sec;
        const char *pos;

        cursor()
                : pos(nullptr) { }
        cursor(const std::shared_ptr<section> sec, section_offset offset = 0)
                : sec(sec), pos(sec->begin + offset) { }

        /**
         * Read a subsection.  The cursor must be at an initial
         * length.  After, the cursor will point just past the end of
         * the subsection.  The returned section has the appropriate
         * DWARF format and begins at the current location of the
         * cursor (so this is usually followed by a
         * skip_initial_length).
         */
        std::shared_ptr<section> subsection();
        std::int64_t sleb128();
        section_offset offset();
        void string(std::string &out);
        const char *cstr(size_t *size_out = nullptr);

        void
        ensure(section_offset bytes)
        {
                if ((section_offset)(sec->end - pos) < bytes || pos >= sec->end)
                        underflow();
        }

        template<typename T>
        T fixed()
        {
                ensure(sizeof(T));
                T val = *(T*)pos;
                pos += sizeof(T);
                return val;
        }

        std::uint64_t uleb128()
        {
                // Appendix C
                // XXX Pre-compute all two byte ULEB's
                std::uint64_t result = 0;
                int shift = 0;
                while (pos < sec->end) {
                        uint8_t byte = *(uint8_t*)(pos++);
                        result |= (uint64_t)(byte & 0x7f) << shift;
                        if ((byte & 0x80) == 0)
                                return result;
                        shift += 7;
                }
                underflow();
                return 0;
        }

        taddr address()
        {
                switch (sec->addr_size) {
                case 1:
                        return fixed<uint8_t>();
                case 2:
                        return fixed<uint16_t>();
                case 4:
                        return fixed<uint32_t>();
                case 8:
                        return fixed<uint64_t>();
                default:
                        throw std::runtime_error("address size " + std::to_string(sec->addr_size) + " not supported");
                }
        }

        void skip_initial_length();
        void skip_form(DW_FORM form);

        cursor &operator+=(section_offset offset)
        {
                pos += offset;
                return *this;
        }

        cursor operator+(section_offset offset) const
        {
                return cursor(sec, pos + offset);
        }

        bool operator<(const cursor &o) const
        {
                return pos < o.pos;
        }

        bool end() const
        {
                return pos >= sec->end;
        }

        bool valid() const
        {
                return !!pos;
        }

        section_offset get_section_offset() const
        {
                return pos - sec->begin;
        }

private:
        cursor(const std::shared_ptr<section> sec, const char *pos)
                : sec(sec), pos(pos) { }

        void underflow();
};

/**
 * An attribute specification in an abbrev.
 */
struct attribute_spec
{
        DW_AT name;
        DW_FORM form;

        // Computed information
        value::type type;

        attribute_spec(DW_AT name, DW_FORM form);
};

typedef std::uint64_t abbrev_code;

/**
 * An entry in .debug_abbrev.
 */
struct abbrev_entry
{
        abbrev_code code;
        DW_TAG tag;
        bool children;
        std::vector<attribute_spec> attributes;

        abbrev_entry() : code(0) { }

        bool read(cursor *cur);
};

/**
 * A section header in .debug_pubnames or .debug_pubtypes.
 */
struct name_unit
{
        uhalf version;
        section_offset debug_info_offset;
        section_length debug_info_length;
        // Cursor to the first name_entry in this unit.  This cursor's
        // section is limited to this unit.
        cursor entries;

        void read(cursor *cur)
        {
                // Section 7.19
                std::shared_ptr<section> subsec = cur->subsection();
                cursor sub(subsec);
                sub.skip_initial_length();
                version = sub.fixed<uhalf>();
                if (version != 2)
                        throw format_error("unknown name unit version " + std::to_string(version));
                debug_info_offset = sub.offset();
                debug_info_length = sub.offset();
                entries = sub;
        }
};

/**
 * An entry in a .debug_pubnames or .debug_pubtypes unit.
 */
struct name_entry
{
        section_offset offset;
        std::string name;

        void read(cursor *cur)
        {
                offset = cur->offset();
                cur->string(name);
        }
};

DWARFPP_END_NAMESPACE

#endif
<|endoftext|>


<commit_before><commit_msg>Casting to float types<commit_after><|endoftext|>


<commit_before>#include <Bull/Core/FileSystem/FileOpeningMode.hpp>
#include <Bull/Core/FileSystem/Win32/FileImplWin32.hpp>
#include <Bull/Core/Support/Win32/DateHelper.hpp>
#include <Bull/Core/Support/Win32/Win32Error.hpp>

namespace Bull
{
    namespace prv
    {
        void FileImplWin32::create(const Path& path)
        {
            HANDLE handler = CreateFile(path.toString().getBuffer(),
                                        GENERIC_READ | GENERIC_WRITE,
                                        FILE_SHARE_READ,
                                        nullptr,
                                        CREATE_NEW,
                                        FILE_ATTRIBUTE_NORMAL,
                                        nullptr);

            Expect(handler != INVALID_HANDLE_VALUE, Throw(Win32Error, "Failed to create file " + path.toString()));

            CloseHandle(handler);
        }

        bool FileImplWin32::exists(const Path& name)
        {
            DWORD attribs = GetFileAttributes(name.toString().getBuffer());

            return (attribs != INVALID_FILE_ATTRIBUTES &&  !(attribs & FILE_ATTRIBUTE_DIRECTORY));
        }

        void FileImplWin32::copy(const Path& path, const Path& newPath)
        {
            Expect(CopyFile(path.toString().getBuffer(), newPath.toString().getBuffer(), true), Throw(Win32Error, "Failed to copy file " + path.toString()));
        }

        void FileImplWin32::rename(const Path& path, const Path& newPath)
        {
            Expect(MoveFile(path.toString().getBuffer(), newPath.toString().getBuffer()), Throw(Win32Error, "Failed to rename file " + path.toString()));
        }

        void FileImplWin32::remove(const Path& path)
        {
            Expect(DeleteFile(path.toString().getBuffer()), Throw(Win32Error, "Failed to remove file " + path.toString()));
        }

        FileImplWin32::FileImplWin32(const Path& path, Uint32 mode)
        {
            DWORD creationMode = 0;
            DWORD openingMode  = 0;

            if(mode & FileOpeningMode_Read)
            {
                openingMode |= GENERIC_READ;

                if(!(mode & FileOpeningMode_Write))
                {
                    creationMode = (mode & FileOpeningMode_Exists) ? OPEN_EXISTING : CREATE_NEW;
                }
            }

            if(mode & FileOpeningMode_Write)
            {
                if(mode & FileOpeningMode_Append)
                {
                    openingMode |= FILE_APPEND_DATA;
                }
                else
                {
                    openingMode |= GENERIC_WRITE;
                }

                if(mode & FileOpeningMode_Truncate)
                {
                    creationMode = CREATE_ALWAYS;
                }
                else if(mode & FileOpeningMode_Exists)
                {
                    creationMode = OPEN_EXISTING;
                }
                else
                {
                    creationMode = exists(path) ? OPEN_EXISTING : CREATE_NEW;
                }
            }

            m_handler = CreateFile(path.toString().getBuffer(),
                                   openingMode,
                                   FILE_SHARE_READ,
                                   nullptr,
                                   creationMode,
                                   FILE_ATTRIBUTE_NORMAL,
                                   nullptr);

            Expect(m_handler != INVALID_HANDLE_VALUE, Throw(Win32Error, "Failed to open file " + path.toString()));
        }

        FileImplWin32::~FileImplWin32()
        {
            CloseHandle(m_handler);
        }

        ByteArray FileImplWin32::read(std::size_t length)
        {
            DWORD read;
            String buffer;
            LARGE_INTEGER cursor;

            ByteArray bytes(length);

            cursor.QuadPart = getCursor();

            LockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(length), 0);
            ReadFile(m_handler, &bytes[0], length, &read, nullptr);
            UnlockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(length), 0);

            bytes.resize(read);

            return bytes;
        }

        std::size_t FileImplWin32::write(const ByteArray& bytes)
        {
            DWORD written = 0;
            LARGE_INTEGER cursor;

            cursor.QuadPart = getCursor();

            LockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(bytes.getCapacity()), 0);
            WriteFile(m_handler, bytes.getBuffer(), static_cast<DWORD>(bytes.getCapacity()), &written, nullptr);
            UnlockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(bytes.getCapacity()), 0);

            return written;
        }

        void FileImplWin32::flush()
        {
            FlushFileBuffers(m_handler);
        }

        DateTime FileImplWin32::getCreationDate() const
        {
            FILETIME date;

            Expect(GetFileTime(m_handler, &date, nullptr, nullptr), Throw(Win32Error, "Failed to get file creation date"));

            SYSTEMTIME sysDate;
            FileTimeToSystemTime(&date, &sysDate);

            return systemTimeToDate(sysDate);
        }

        DateTime FileImplWin32::getLastAccessDate() const
        {
            FILETIME date;

            Expect(GetFileTime(m_handler, &date, nullptr, nullptr), Throw(Win32Error, "Failed to get file last access date"));

            SYSTEMTIME sysDate;
            FileTimeToSystemTime(&date, &sysDate);

            return systemTimeToDate(sysDate);
        }

        DateTime FileImplWin32::getLastWriteDate() const
        {
            FILETIME date;

            Expect(GetFileTime(m_handler, &date, nullptr, nullptr), Throw(Win32Error, "Failed to get file last write date"));

            SYSTEMTIME sysDate;
            FileTimeToSystemTime(&date, &sysDate);

            return systemTimeToDate(sysDate);
        }

        std::size_t FileImplWin32::getCursor() const
        {
            LARGE_INTEGER zero = {0};
            LARGE_INTEGER position;

            Expect(SetFilePointerEx(m_handler, zero, &position, FILE_CURRENT), Throw(Win32Error, "Failed to get file cursor"));

            return static_cast<std::size_t>(position.QuadPart);
        }

        std::size_t FileImplWin32::moveCursor(Int64 offset)
        {
            LARGE_INTEGER distance;
            LARGE_INTEGER position;
            distance.QuadPart = offset;

            Expect(SetFilePointerEx(m_handler, distance, &position, FILE_CURRENT), Throw(Win32Error, "Failed to move file cursor"));

            return position.QuadPart;
        }

        std::size_t FileImplWin32::setCursor(std::size_t offset)
        {
            LARGE_INTEGER distance;
            LARGE_INTEGER position;
            distance.QuadPart = offset;

            Expect(SetFilePointerEx(m_handler, distance, &position, FILE_BEGIN), Throw(Win32Error, "Failed to set file cursor"));

            return position.QuadPart;
        }

        std::size_t FileImplWin32::getSize() const
        {
            LARGE_INTEGER size;

            GetFileSizeEx(m_handler, &size);

            return size.QuadPart;
        }
    }
}
<commit_msg>[Core/FileImplWin32] Check if WriteFile was successful<commit_after>#include <Bull/Core/FileSystem/FileOpeningMode.hpp>
#include <Bull/Core/FileSystem/Win32/FileImplWin32.hpp>
#include <Bull/Core/Support/Win32/DateHelper.hpp>
#include <Bull/Core/Support/Win32/Win32Error.hpp>

namespace Bull
{
    namespace prv
    {
        void FileImplWin32::create(const Path& path)
        {
            HANDLE handler = CreateFile(path.toString().getBuffer(),
                                        GENERIC_READ | GENERIC_WRITE,
                                        FILE_SHARE_READ,
                                        nullptr,
                                        CREATE_NEW,
                                        FILE_ATTRIBUTE_NORMAL,
                                        nullptr);

            Expect(handler != INVALID_HANDLE_VALUE, Throw(Win32Error, "Failed to create file " + path.toString()));

            CloseHandle(handler);
        }

        bool FileImplWin32::exists(const Path& name)
        {
            DWORD attribs = GetFileAttributes(name.toString().getBuffer());

            return (attribs != INVALID_FILE_ATTRIBUTES &&  !(attribs & FILE_ATTRIBUTE_DIRECTORY));
        }

        void FileImplWin32::copy(const Path& path, const Path& newPath)
        {
            Expect(CopyFile(path.toString().getBuffer(), newPath.toString().getBuffer(), true), Throw(Win32Error, "Failed to copy file " + path.toString()));
        }

        void FileImplWin32::rename(const Path& path, const Path& newPath)
        {
            Expect(MoveFile(path.toString().getBuffer(), newPath.toString().getBuffer()), Throw(Win32Error, "Failed to rename file " + path.toString()));
        }

        void FileImplWin32::remove(const Path& path)
        {
            Expect(DeleteFile(path.toString().getBuffer()), Throw(Win32Error, "Failed to remove file " + path.toString()));
        }

        FileImplWin32::FileImplWin32(const Path& path, Uint32 mode)
        {
            DWORD creationMode = 0;
            DWORD openingMode  = 0;

            if(mode & FileOpeningMode_Read)
            {
                openingMode |= GENERIC_READ;

                if(!(mode & FileOpeningMode_Write))
                {
                    creationMode = (mode & FileOpeningMode_Exists) ? OPEN_EXISTING : CREATE_NEW;
                }
            }

            if(mode & FileOpeningMode_Write)
            {
                if(mode & FileOpeningMode_Append)
                {
                    openingMode |= FILE_APPEND_DATA;
                }
                else
                {
                    openingMode |= GENERIC_WRITE;
                }

                if(mode & FileOpeningMode_Truncate)
                {
                    creationMode = CREATE_ALWAYS;
                }
                else if(mode & FileOpeningMode_Exists)
                {
                    creationMode = OPEN_EXISTING;
                }
                else
                {
                    creationMode = exists(path) ? OPEN_EXISTING : CREATE_NEW;
                }
            }

            m_handler = CreateFile(path.toString().getBuffer(),
                                   openingMode,
                                   FILE_SHARE_READ,
                                   nullptr,
                                   creationMode,
                                   FILE_ATTRIBUTE_NORMAL,
                                   nullptr);

            Expect(m_handler != INVALID_HANDLE_VALUE, Throw(Win32Error, "Failed to open file " + path.toString()));
        }

        FileImplWin32::~FileImplWin32()
        {
            CloseHandle(m_handler);
        }

        ByteArray FileImplWin32::read(std::size_t length)
        {
            DWORD read;
            String buffer;
            LARGE_INTEGER cursor;

            ByteArray bytes(length);

            cursor.QuadPart = getCursor();

            LockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(length), 0);
            ReadFile(m_handler, &bytes[0], length, &read, nullptr);
            UnlockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(length), 0);

            bytes.resize(read);

            return bytes;
        }

        std::size_t FileImplWin32::write(const ByteArray& bytes)
        {
            DWORD written = 0;
            LARGE_INTEGER cursor;

            cursor.QuadPart = getCursor();

            LockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(bytes.getCapacity()), 0);
            BOOL success = WriteFile(m_handler, bytes.getBuffer(), static_cast<DWORD>(bytes.getCapacity()), &written, nullptr);
            UnlockFile(m_handler, cursor.LowPart, cursor.HighPart, static_cast<DWORD>(bytes.getCapacity()), 0);

            Expect(success, Throw(Win32Error, "Failed to write into file"));

            return written;
        }

        void FileImplWin32::flush()
        {
            FlushFileBuffers(m_handler);
        }

        DateTime FileImplWin32::getCreationDate() const
        {
            FILETIME date;

            Expect(GetFileTime(m_handler, &date, nullptr, nullptr), Throw(Win32Error, "Failed to get file creation date"));

            SYSTEMTIME sysDate;
            FileTimeToSystemTime(&date, &sysDate);

            return systemTimeToDate(sysDate);
        }

        DateTime FileImplWin32::getLastAccessDate() const
        {
            FILETIME date;

            Expect(GetFileTime(m_handler, &date, nullptr, nullptr), Throw(Win32Error, "Failed to get file last access date"));

            SYSTEMTIME sysDate;
            FileTimeToSystemTime(&date, &sysDate);

            return systemTimeToDate(sysDate);
        }

        DateTime FileImplWin32::getLastWriteDate() const
        {
            FILETIME date;

            Expect(GetFileTime(m_handler, &date, nullptr, nullptr), Throw(Win32Error, "Failed to get file last write date"));

            SYSTEMTIME sysDate;
            FileTimeToSystemTime(&date, &sysDate);

            return systemTimeToDate(sysDate);
        }

        std::size_t FileImplWin32::getCursor() const
        {
            LARGE_INTEGER zero = {0};
            LARGE_INTEGER position;

            Expect(SetFilePointerEx(m_handler, zero, &position, FILE_CURRENT), Throw(Win32Error, "Failed to get file cursor"));

            return static_cast<std::size_t>(position.QuadPart);
        }

        std::size_t FileImplWin32::moveCursor(Int64 offset)
        {
            LARGE_INTEGER distance;
            LARGE_INTEGER position;
            distance.QuadPart = offset;

            Expect(SetFilePointerEx(m_handler, distance, &position, FILE_CURRENT), Throw(Win32Error, "Failed to move file cursor"));

            return position.QuadPart;
        }

        std::size_t FileImplWin32::setCursor(std::size_t offset)
        {
            LARGE_INTEGER distance;
            LARGE_INTEGER position;
            distance.QuadPart = offset;

            Expect(SetFilePointerEx(m_handler, distance, &position, FILE_BEGIN), Throw(Win32Error, "Failed to set file cursor"));

            return position.QuadPart;
        }

        std::size_t FileImplWin32::getSize() const
        {
            LARGE_INTEGER size;

            GetFileSizeEx(m_handler, &size);

            return size.QuadPart;
        }
    }
}
<|endoftext|>


<commit_before>//
// RemotePhotoTool - remote camera control software
// Copyright (C) 2008-2014 Michael Fink
//
/// \file PsrecSourceDeviceImpl.hpp PS-ReC - SourceDevice impl
//
#pragma once

// includes
#include "SourceDevice.hpp"
#include "PsrecCommon.hpp"
#include "PsrecRemoteReleaseControlImpl.hpp"
#include "PsrecPropertyAccess.hpp"
#include "PsrecDeviceInfo.hpp"

namespace PSREC
{

/// source device impl for PSREC
class SourceDeviceImpl:
   public SourceDevice,
   public std::enable_shared_from_this<SourceDeviceImpl>
{
public:
   /// ctor
   SourceDeviceImpl(RefSp spRef, prDeviceInfoTable& deviceInfo)
      :m_spRef(spRef),
       m_hCamera(0)
   {
      LOG_TRACE(_T("about to call PR_CreateCameraObject...\n"));

      prHandle hCamera = 0;
      // may return prINVALID_FN_CALL when SDK wasn't initialized
      // may return prINVALID_PARAMETER when specified device info is invalid
      // may return prMEM_ALLOC_FAILED on memory error
      prResponse err = PR_CreateCameraObject(&deviceInfo, &hCamera);
      LOG_TRACE(_T("PR_CreateCameraObject(&si = \"%ls\", &handle) returned %08x, handle %08x\n"),
         deviceInfo.ModelName, err, hCamera);
      CheckError(_T("PR_CreateCameraObject"), err, __FILE__, __LINE__);

      m_hCamera = hCamera;

      // connect to camera itself
      // may return prINVALID_FN_CALL, prINVALID_HANDLE, prMEM_ALLOC_FAILED
      err = PR_ConnectCamera(m_hCamera);
      LOG_TRACE(_T("PR_ConnectCamera(handle = %08x) returned %08x\n"), m_hCamera, err);
      CheckError(_T("PR_ConnectCamera"), err, __FILE__, __LINE__);

      // get device info so that we don't have to query every time
      m_spDeviceInfo.reset(new DeviceInfo(m_hCamera));
   }

   /// dtor
   virtual ~SourceDeviceImpl() throw()
   {
      // disconnect from camera
      prResponse err = PR_DisconnectCamera(m_hCamera);
      LOG_TRACE(_T("PR_DisconnectCamera(%08x) returned %08x\n"), m_hCamera, err);

      // may return prINVALID_FN_CALL when SDK wasn't initialized
      // may return prINVALID_HANDLE when specified handle is invalid
      err = PR_DestroyCameraObject(m_hCamera);
      LOG_TRACE(_T("PR_DestroyCameraObject(%08x) returned %08x\n"), m_hCamera, err);
   }

   virtual bool GetDeviceCapability(SourceDevice::T_enDeviceCapability enDeviceCapability) const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);
      DeviceInfo& info = *m_spDeviceInfo.get();

      switch (enDeviceCapability)
      {
      case SourceDevice::capRemoteReleaseControl:
         {
            bool bInitiateRelease =
               info.m_setOperationsSupported.find(prPTP_INITIATE_RELEASE_CONTROL) != info.m_setOperationsSupported.end();
            return bInitiateRelease;
         }
         break;

      case SourceDevice::capRemoteViewfinder:
         {
            bool bInitiateViewfinder =
               info.m_setOperationsSupported.find(prPTP_RC_INITIATE_VIEW_FINDER) != info.m_setOperationsSupported.end();

            return bInitiateViewfinder;
         }
         break;

      case SourceDevice::capCameraFileSystem:
         return false; // not supported by PS-ReC

      default:
         ATLASSERT(false);
      }
      return false;
   }

   virtual CString ModelName() const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);

      return m_spDeviceInfo->m_cszModel;
   }

   virtual CString SerialNumber() const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);

      return m_spDeviceInfo->m_cszSerialNumber;
   }

   virtual std::vector<unsigned int> EnumDeviceProperties() const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);
      DeviceInfo& info = *m_spDeviceInfo.get();

      const std::set<prUInt16>& setDeviceProperties =  info.m_setDevicePropertiesSupported;
      std::set<prUInt16>::const_iterator iter = setDeviceProperties.begin(),
         stop = setDeviceProperties.end();

      std::vector<unsigned int> vecData;

      // just put the device property id's into the vector
      for (; iter != stop; ++iter)
         vecData.push_back(*iter);

      return vecData;
   }

   virtual DeviceProperty GetDeviceProperty(unsigned int uiPropertyId) const override
   {
      prUInt16 propId = static_cast<prUInt16>(uiPropertyId & 0xFFFF);

      // get device property value
      DevicePropDesc desc(m_hCamera, propId, true);

      DeviceProperty dp(variantPsrec, uiPropertyId, desc.m_varCurrentValue, !desc.IsSetAllowed());
      dp.m_vecValidValues = desc.m_vecAllValues;

      return dp;
   }

   virtual std::shared_ptr<CameraFileSystem> GetFileSystem() override
   {
      if (!GetDeviceCapability(capCameraFileSystem))
      {
         throw CameraException(_T("PSREC::SourceDevice::GetFileSystem"), _T("Not supported"),
            prERROR_PRSDK_COMPONENTID | prNOT_SUPPORTED, __FILE__, __LINE__);
      }

      return std::shared_ptr<CameraFileSystem>();
   }

   virtual std::shared_ptr<RemoteReleaseControl> EnterReleaseControl() override
   {
      if (!GetDeviceCapability(capRemoteReleaseControl))
      {
         throw CameraException(_T("PSREC::SourceDevice::EnterReleaseControl"), _T("Not supported"),
            prERROR_PRSDK_COMPONENTID | prNOT_SUPPORTED, __FILE__, __LINE__);
      }

      std::shared_ptr<SourceDeviceImpl> spSourceDevice = shared_from_this();

      return std::shared_ptr<RemoteReleaseControl>(new RemoteReleaseControlImpl(m_hCamera, spSourceDevice));
   }

   /// returns device info
   std::shared_ptr<DeviceInfo> GetDeviceInfo() { return m_spDeviceInfo; }

private:
   /// camera handle
   prHandle m_hCamera;

   /// SDK ref
   RefSp m_spRef;

   /// device info
   std::shared_ptr<DeviceInfo> m_spDeviceInfo;
};

} // namespace PSREC
<commit_msg>implemented PS-ReC support for CameraFileSystem by using WIA<commit_after>//
// RemotePhotoTool - remote camera control software
// Copyright (C) 2008-2017 Michael Fink
//
/// \file PsrecSourceDeviceImpl.hpp PS-ReC - SourceDevice impl
//
#pragma once

// includes
#include "SourceDevice.hpp"
#include "PsrecCommon.hpp"
#include "PsrecRemoteReleaseControlImpl.hpp"
#include "PsrecPropertyAccess.hpp"
#include "PsrecDeviceInfo.hpp"
#include "../WIA/WiaCommon.hpp"
#include "../WIA/WiaSourceInfoImpl.hpp"

namespace PSREC
{

/// source device impl for PSREC
class SourceDeviceImpl:
   public SourceDevice,
   public std::enable_shared_from_this<SourceDeviceImpl>
{
public:
   /// ctor
   SourceDeviceImpl(RefSp spRef, prDeviceInfoTable& deviceInfo)
      :m_spRef(spRef),
       m_hCamera(0),
       m_deviceId(reinterpret_cast<wchar_t*>(deviceInfo.DeviceInternalName))
   {
      LOG_TRACE(_T("about to call PR_CreateCameraObject...\n"));

      prHandle hCamera = 0;
      // may return prINVALID_FN_CALL when SDK wasn't initialized
      // may return prINVALID_PARAMETER when specified device info is invalid
      // may return prMEM_ALLOC_FAILED on memory error
      prResponse err = PR_CreateCameraObject(&deviceInfo, &hCamera);
      LOG_TRACE(_T("PR_CreateCameraObject(&si = \"%ls\", &handle) returned %08x, handle %08x\n"),
         deviceInfo.ModelName, err, hCamera);
      CheckError(_T("PR_CreateCameraObject"), err, __FILE__, __LINE__);

      m_hCamera = hCamera;

      // connect to camera itself
      // may return prINVALID_FN_CALL, prINVALID_HANDLE, prMEM_ALLOC_FAILED
      err = PR_ConnectCamera(m_hCamera);
      LOG_TRACE(_T("PR_ConnectCamera(handle = %08x) returned %08x\n"), m_hCamera, err);
      CheckError(_T("PR_ConnectCamera"), err, __FILE__, __LINE__);

      // get device info so that we don't have to query every time
      m_spDeviceInfo.reset(new DeviceInfo(m_hCamera));
   }

   /// dtor
   virtual ~SourceDeviceImpl() throw()
   {
      // disconnect from camera
      prResponse err = PR_DisconnectCamera(m_hCamera);
      LOG_TRACE(_T("PR_DisconnectCamera(%08x) returned %08x\n"), m_hCamera, err);

      // may return prINVALID_FN_CALL when SDK wasn't initialized
      // may return prINVALID_HANDLE when specified handle is invalid
      err = PR_DestroyCameraObject(m_hCamera);
      LOG_TRACE(_T("PR_DestroyCameraObject(%08x) returned %08x\n"), m_hCamera, err);
   }

   virtual bool GetDeviceCapability(SourceDevice::T_enDeviceCapability enDeviceCapability) const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);
      DeviceInfo& info = *m_spDeviceInfo.get();

      switch (enDeviceCapability)
      {
      case SourceDevice::capRemoteReleaseControl:
         {
            bool bInitiateRelease =
               info.m_setOperationsSupported.find(prPTP_INITIATE_RELEASE_CONTROL) != info.m_setOperationsSupported.end();
            return bInitiateRelease;
         }
         break;

      case SourceDevice::capRemoteViewfinder:
         {
            bool bInitiateViewfinder =
               info.m_setOperationsSupported.find(prPTP_RC_INITIATE_VIEW_FINDER) != info.m_setOperationsSupported.end();

            return bInitiateViewfinder;
         }
         break;

      case SourceDevice::capCameraFileSystem:
         return true; // supported through WIA

      default:
         ATLASSERT(false);
      }
      return false;
   }

   virtual CString ModelName() const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);

      return m_spDeviceInfo->m_cszModel;
   }

   virtual CString SerialNumber() const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);

      return m_spDeviceInfo->m_cszSerialNumber;
   }

   virtual std::vector<unsigned int> EnumDeviceProperties() const override
   {
      ATLASSERT(m_spDeviceInfo != nullptr);
      DeviceInfo& info = *m_spDeviceInfo.get();

      const std::set<prUInt16>& setDeviceProperties =  info.m_setDevicePropertiesSupported;
      std::set<prUInt16>::const_iterator iter = setDeviceProperties.begin(),
         stop = setDeviceProperties.end();

      std::vector<unsigned int> vecData;

      // just put the device property id's into the vector
      for (; iter != stop; ++iter)
         vecData.push_back(*iter);

      return vecData;
   }

   virtual DeviceProperty GetDeviceProperty(unsigned int uiPropertyId) const override
   {
      prUInt16 propId = static_cast<prUInt16>(uiPropertyId & 0xFFFF);

      // get device property value
      DevicePropDesc desc(m_hCamera, propId, true);

      DeviceProperty dp(variantPsrec, uiPropertyId, desc.m_varCurrentValue, !desc.IsSetAllowed());
      dp.m_vecValidValues = desc.m_vecAllValues;

      return dp;
   }

   virtual std::shared_ptr<CameraFileSystem> GetFileSystem() override
   {
      if (!GetDeviceCapability(capCameraFileSystem))
      {
         throw CameraException(_T("PSREC::SourceDevice::GetFileSystem"), _T("Not supported"),
            prERROR_PRSDK_COMPONENTID | prNOT_SUPPORTED, __FILE__, __LINE__);
      }

      // support file system using WIA
      WIA::RefSp wiaRef = std::make_shared<WIA::Ref>();
      std::shared_ptr<SourceInfo> sourceInfo = std::make_shared<WIA::SourceInfoImpl>(wiaRef, m_deviceId, m_spDeviceInfo->m_cszModel);

      std::shared_ptr<SourceDevice> sourceDevice = sourceInfo->Open();

      return sourceDevice->GetFileSystem();
   }

   virtual std::shared_ptr<RemoteReleaseControl> EnterReleaseControl() override
   {
      if (!GetDeviceCapability(capRemoteReleaseControl))
      {
         throw CameraException(_T("PSREC::SourceDevice::EnterReleaseControl"), _T("Not supported"),
            prERROR_PRSDK_COMPONENTID | prNOT_SUPPORTED, __FILE__, __LINE__);
      }

      std::shared_ptr<SourceDeviceImpl> spSourceDevice = shared_from_this();

      return std::shared_ptr<RemoteReleaseControl>(new RemoteReleaseControlImpl(m_hCamera, spSourceDevice));
   }

   /// returns device info
   std::shared_ptr<DeviceInfo> GetDeviceInfo() { return m_spDeviceInfo; }

private:
   /// camera handle
   prHandle m_hCamera;

   /// SDK ref
   RefSp m_spRef;

   /// device info
   std::shared_ptr<DeviceInfo> m_spDeviceInfo;

   /// device id
   CString m_deviceId;
};

} // namespace PSREC
<|endoftext|>


<commit_before>#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/tracking.hpp>

#include <string>
#include <iostream>
#include <vector>

using Color = cv::Vec4b;
using Image = cv::Mat_<Color>;
using Data = cv::Mat_<uchar>;
using Flow = cv::Mat_<cv::Vec2f>;

const Color TRANSPARENT(0,0,0,0);

enum {
    TYPE_NO_DATA,
    TYPE_NONE,
    TYPE_CLOUD,
    TYPE_RAIN,
    TYPE_STORM,
    TYPE_HAIL,
    TYPE_UNKNOWN
};

namespace color_detector {

    bool is_cloud_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return b > 0.8*g && g > 0.4*b && b > 3*r;
    }

    bool is_rain_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return b > 3*g && b > 3*r;
    }

    bool is_storm_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return (r > 1.3*g && r > 3*b);
    }

    bool is_hail_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return ((g > 3*r && g > 3*b) // greens
            || (r > 3*g && b > 3*g && r > 0.5*b && b > 0.5*r)); // violets
    }

    bool is_none_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        int a = (r + g + b)/3;
        return (r > 0.8*a && g > 0.8*a && b > 0.8*a && a < 160 && a > 60)  // grays
            || (r > 3*b && g > 3*b && r > 0.8*g && g > 0.8*r);  // yellows
    }

    bool is_no_data_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        int a = (r + g + b)/3;
        return (r > 0.8*a && g > 0.8*a && b > 0.8*a && a >= 160);
    }

    int detect(const Color& color) {
        if (is_hail_color(color))
            return TYPE_HAIL;
        else if (is_storm_color(color))
            return TYPE_STORM;
        else if (is_rain_color(color))
            return TYPE_RAIN;
        else if (is_cloud_color(color))
            return TYPE_CLOUD;
        else if (is_none_color(color))
            return TYPE_NONE;
        else if (is_no_data_color(color))
            return TYPE_NO_DATA;
        else
            return TYPE_UNKNOWN;
    }
}

bool isFixedColor(const std::vector<Image>& frames, int x, int y) {
    auto col = frames[0](y, x);
    //if (color_detector::is_none_color(col))
        //return false;
    for (const auto& frame: frames) {
        if (frame(y, x) != col)
            return false;
    }
    return true;
}

std::vector<int> makeDd(int max) {
    std::vector<int> dd;
    for (int x = 0; x <= max; x++)
        for (int s: {-1, 1})
            dd.push_back(x * s);
    return dd;
}

template<class M>
bool goodPoint(const M& im, int x, int y) {
    return (x>=0) && (x<im.cols) && (y>=0) && (y<im.rows);
}

std::vector<Image> loadImages(const std::string& filename) {
    std::string fname = filename;
    std::vector<Image> frames;
    for (int frame = 0; frame <= 18; frame++) {
        char buffer[100];
        sprintf(buffer, fname.c_str(), frame);
        frames.push_back(cv::imread(buffer, -1));
    }
    return frames;
}

std::vector<Data> convertToDatas(const std::vector<Image>& frames) {
    Data fixeds = Data::zeros(frames[0].rows, frames[0].cols);
    for (int y = 0; y < fixeds.rows; y++) {
        for (int x = 0; x < fixeds.cols; x++) {
            fixeds(y, x) = isFixedColor(frames, x, y);
        }
    }

    //colorize(fixeds);
    //return 0;

    auto dd = makeDd(2);

    std::vector<Data> sourceDataFrames;
    for (const auto& frame: frames) {
        sourceDataFrames.emplace_back(Data::zeros(frame.rows, frame.cols));
        for (int y = 0; y < frame.rows; y++) {
            for (int x = 0; x < frame.cols; x++) {
                sourceDataFrames.back()(y, x) = color_detector::detect(frame(y, x));
            }
        }
    }

    std::vector<Data> dataFrames;
    for (const auto& frame: sourceDataFrames) {
        dataFrames.emplace_back(Data::zeros(frame.rows, frame.cols));
        for (int y = 0; y < frame.rows; y++) {
            for (int x = 0; x < frame.cols; x++) {
                bool found = false;
                bool wasNone = false;
                bool wasNoData = false;
                for (int dx: dd) {
                    for (int dy: dd) {
                        int xx = x + dx;
                        int yy = y + dy;
                        if (goodPoint(frame, xx, yy)) {
                            auto color = frame(yy, xx);
                            if (!fixeds(yy, xx)) {
                                dataFrames.back()(y, x) = color;
                                found = true;
                                break;
                            }
                            wasNone |= (color == TYPE_NONE);
                            wasNoData |= (color == TYPE_NO_DATA);
                        }
                    }
                    if (found) break;
                }
                if (!found) {
                    if (wasNone)
                        dataFrames.back()(y, x) = TYPE_NONE;
                    else if (wasNoData)
                        dataFrames.back()(y, x) = TYPE_NO_DATA;
                    else
                        dataFrames.back()(y, x) = frame(y, x);
                }
            }
        }
    }

    dd = makeDd(dataFrames.size());

    for (int i = 0; i < dataFrames.size(); i++) {
        auto& frame = dataFrames[i];
        for (int y = 0; y < frame.rows; y++) {
            for (int x = 0; x < frame.cols; x++) {
                if (frame(y, x) == TYPE_NO_DATA) {
                    for (int di: dd) {
                        int ii = i + di;
                        if (ii < 0 || ii >= dataFrames.size()) continue;
                        const auto& frame2 = dataFrames[ii];
                        if (frame2(y, x) != TYPE_NO_DATA) {
                            frame(y, x) = frame2(y, x);
                        }
                    }
                }
                if (frame(y, x) == TYPE_NO_DATA)
                    frame(y, x) = TYPE_NONE;
            }
        }
    }

    return dataFrames;
}

void colorize(const Data& data, const std::string& filename) {
    static const std::vector<Color> COLORS{
        {0, 0, 0, 255},
        {128, 128, 128, 255},
        {128, 0, 0, 255},
        {255, 0, 0, 255},
        {0, 0, 255, 255},
        {0, 255, 0, 255},
        {255, 255, 255}
    };
    Image im(data.rows, data.cols, TRANSPARENT);
    for (int y = 0; y < data.rows; y++)
        for (int x = 0; x < data.cols; x++) {
            im(y, x) = COLORS[data(y,x)];
        }

    std::vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(9);
    cv::imwrite(filename + ".png", im, compression_params);
}

void colorize(const std::vector<Data>& data, const std::string& filename) {
    for (int i = 0; i < data.size(); i++) {
        char buffer[100];
        sprintf(buffer, filename.c_str(), i);
        colorize(data[i], buffer);
    }
}

void colorize(const Flow& flow, const std::string& filename) {
    cv::Mat3f im(flow.rows, flow.cols, cv::Vec3f(0, 0, 0));
    for (int y = 0; y < flow.rows; y++)
        for (int x = 0; x < flow.cols; x++) {
            float vx = flow(y, x)[0];
            float vy = flow(y, x)[1];
            float v = sqrt(vx*vx + vy*vy);
            float dir = atan2(vy, vx);
            if (dir < 0) dir += 2*M_PI;
            float h = dir / 2 / M_PI * 360;
            float val = v * 3e3;
            if (val > 0.5) std::cout << vx << " " << vy << " " << v << std::endl;
            im(y, x) = {h, 1, val};
        }
    std::cout << im(100, 100) << std::endl;

    cv::Mat4f converted;
    cv::cvtColor(im, converted, cv::COLOR_HSV2BGR, 4);
    Image result = converted * 256;
    //result *= 256;
    std::cout << result(100, 100) << std::endl;
    //result = im;
    std::vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(9);
    cv::imwrite(filename + ".png", result, compression_params);
}

int main(int argc, char* argv[]) {

    auto images = loadImages(argv[1]);
    auto datas = convertToDatas(images);

    Flow flow;
    //cv::calcOpticalFlowFarneback(datas[0], datas[1], flow, 0.3, 20, 70, 2, 7, 1.7, cv::OPTFLOW_FARNEBACK_GAUSSIAN);
    cv::calcOpticalFlowSparseToDense(datas[0], datas[1], flow);
    /*
    for (int i = 2; i < datas.size(); i++) {
        Flow flow2;
        cv::calcOpticalFlowFarneback(datas[i-1], datas[i], flow2, 0.3, 20, 70, 2, 7, 1.7, cv::OPTFLOW_FARNEBACK_GAUSSIAN);
        flow += flow2;
    }
    */

    colorize(datas, "test%02d");
    colorize(flow, "test");

    return 0;
}
<commit_msg>Attemt to use sparse optical flow<commit_after>#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/tracking.hpp>

#include <string>
#include <iostream>
#include <vector>

using Color = cv::Vec4b;
using Image = cv::Mat_<Color>;
using Data = cv::Mat_<uchar>;
using Flow = cv::Mat_<cv::Vec2f>;

const Color TRANSPARENT(0,0,0,0);

enum {
    TYPE_NO_DATA,
    TYPE_NONE,
    TYPE_CLOUD,
    TYPE_RAIN,
    TYPE_STORM,
    TYPE_HAIL,
    TYPE_UNKNOWN
};

namespace color_detector {

    bool is_cloud_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return b > 0.8*g && g > 0.4*b && b > 3*r;
    }

    bool is_rain_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return b > 3*g && b > 3*r;
    }

    bool is_storm_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return (r > 1.3*g && r > 3*b);
    }

    bool is_hail_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        return ((g > 2*r && g > 3*b) // greens
            || (r > 3*g && b > 3*g && r > 0.5*b && b > 0.5*r)); // violets
    }

    bool is_none_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        int a = (r + g + b)/3;
        return (r > 0.8*a && g > 0.8*a && b > 0.8*a && a < 160 && a > 60)  // grays
            || (r > 3*b && g > 3*b && r > 0.8*g && g > 0.8*r);  // yellows
    }

    bool is_no_data_color(const Color& color) {
        int r = color[2];
        int g = color[1];
        int b = color[0];
        int a = (r + g + b)/3;
        return (r > 0.8*a && g > 0.8*a && b > 0.8*a && a >= 160);
    }

    int detect(const Color& color) {
        if (is_hail_color(color))
            return TYPE_HAIL;
        else if (is_storm_color(color))
            return TYPE_STORM;
        else if (is_rain_color(color))
            return TYPE_RAIN;
        else if (is_cloud_color(color))
            return TYPE_CLOUD;
        else if (is_none_color(color))
            return TYPE_NONE;
        else if (is_no_data_color(color))
            return TYPE_NO_DATA;
        else
            return TYPE_UNKNOWN;
    }
}

bool isFixedColor(const std::vector<Image>& frames, int x, int y) {
    auto col = frames[0](y, x);
    //if (color_detector::is_none_color(col))
        //return false;
    for (const auto& frame: frames) {
        if (frame(y, x) != col)
            return false;
    }
    return true;
}

std::vector<int> makeDd(int max) {
    std::vector<int> dd;
    for (int x = 0; x <= max; x++)
        for (int s: {-1, 1})
            dd.push_back(x * s);
    return dd;
}

template<class M>
bool goodPoint(const M& im, int x, int y) {
    return (x>=0) && (x<im.cols) && (y>=0) && (y<im.rows);
}

std::vector<Image> loadImages(const std::string& filename) {
    std::string fname = filename;
    std::vector<Image> frames;
    for (int frame = 0; frame <= 18; frame++) {
        char buffer[100];
        sprintf(buffer, fname.c_str(), frame);
        frames.push_back(cv::imread(buffer, -1));
    }
    return frames;
}

std::vector<Data> convertToDatas(const std::vector<Image>& frames) {
    Data fixeds = Data::zeros(frames[0].rows, frames[0].cols);
    for (int y = 0; y < fixeds.rows; y++) {
        for (int x = 0; x < fixeds.cols; x++) {
            fixeds(y, x) = isFixedColor(frames, x, y);
        }
    }

    //colorize(fixeds);
    //return 0;

    auto dd = makeDd(2);

    std::vector<Data> sourceDataFrames;
    for (const auto& frame: frames) {
        sourceDataFrames.emplace_back(Data::zeros(frame.rows, frame.cols));
        for (int y = 0; y < frame.rows; y++) {
            for (int x = 0; x < frame.cols; x++) {
                sourceDataFrames.back()(y, x) = color_detector::detect(frame(y, x));
            }
        }
    }

    std::vector<Data> dataFrames;
    for (const auto& frame: sourceDataFrames) {
        dataFrames.emplace_back(Data::zeros(frame.rows, frame.cols));
        for (int y = 0; y < frame.rows; y++) {
            for (int x = 0; x < frame.cols; x++) {
                bool found = false;
                bool wasNone = false;
                bool wasNoData = false;
                for (int dx: dd) {
                    for (int dy: dd) {
                        int xx = x + dx;
                        int yy = y + dy;
                        if (goodPoint(frame, xx, yy)) {
                            auto color = frame(yy, xx);
                            if (!fixeds(yy, xx)) {
                                dataFrames.back()(y, x) = color;
                                found = true;
                                break;
                            }
                            wasNone |= (color == TYPE_NONE);
                            wasNoData |= (color == TYPE_NO_DATA);
                        }
                    }
                    if (found) break;
                }
                if (!found) {
                    if (wasNone)
                        dataFrames.back()(y, x) = TYPE_NONE;
                    else if (wasNoData)
                        dataFrames.back()(y, x) = TYPE_NO_DATA;
                    else
                        dataFrames.back()(y, x) = frame(y, x);
                }
            }
        }
    }

    dd = makeDd(dataFrames.size());

    for (int i = 0; i < dataFrames.size(); i++) {
        auto& frame = dataFrames[i];
        for (int y = 0; y < frame.rows; y++) {
            for (int x = 0; x < frame.cols; x++) {
                if (frame(y, x) == TYPE_NO_DATA) {
                    for (int di: dd) {
                        int ii = i + di;
                        if (ii < 0 || ii >= dataFrames.size()) continue;
                        const auto& frame2 = dataFrames[ii];
                        if (frame2(y, x) != TYPE_NO_DATA) {
                            frame(y, x) = frame2(y, x);
                        }
                    }
                }
                if (frame(y, x) == TYPE_NO_DATA)
                    frame(y, x) = TYPE_NONE;
            }
        }
    }

    return dataFrames;
}

void colorize(const Data& data, const std::string& filename) {
    static const std::vector<Color> COLORS{
        {0, 0, 0, 255},
        {128, 128, 128, 255},
        {128, 0, 0, 255},
        {255, 0, 0, 255},
        {0, 0, 255, 255},
        {0, 255, 0, 255},
        {255, 0, 255, 255}
    };
    Image im(data.rows, data.cols, TRANSPARENT);
    for (int y = 0; y < data.rows; y++)
        for (int x = 0; x < data.cols; x++) {
            im(y, x) = COLORS[data(y,x)];
        }

    std::vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(9);
    cv::imwrite(filename + ".png", im, compression_params);
}

void colorize(const std::vector<Data>& data, const std::string& filename) {
    for (int i = 0; i < data.size(); i++) {
        char buffer[100];
        sprintf(buffer, filename.c_str(), i);
        colorize(data[i], buffer);
    }
}

void colorize(const Flow& flow, const std::string& filename) {
    cv::Mat3f im(flow.rows, flow.cols, cv::Vec3f(0, 0, 0));
    for (int y = 0; y < flow.rows; y++)
        for (int x = 0; x < flow.cols; x++) {
            float vx = flow(y, x)[0];
            float vy = flow(y, x)[1];
            float v = sqrt(vx*vx + vy*vy);
            float dir = atan2(vy, vx);
            if (dir < 0) dir += 2*M_PI;
            float h = dir / 2 / M_PI * 360;
            float val = v * 3e3;
            if (val > 0.5) std::cout << vx << " " << vy << " " << v << std::endl;
            im(y, x) = {h, 1, val};
        }
    std::cout << im(100, 100) << std::endl;

    cv::Mat4f converted;
    cv::cvtColor(im, converted, cv::COLOR_HSV2BGR, 4);
    Image result = converted * 256;
    //result *= 256;
    std::cout << result(100, 100) << std::endl;
    //result = im;
    std::vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(9);
    cv::imwrite(filename + ".png", result, compression_params);
}

int main(int argc, char* argv[]) {

    auto images = loadImages(argv[1]);
    auto datas = convertToDatas(images);

    Flow flow;
    //cv::calcOpticalFlowFarneback(datas[0], datas[1], flow, 0.3, 20, 70, 2, 7, 1.7, cv::OPTFLOW_FARNEBACK_GAUSSIAN);
    //cv::calcOpticalFlowSparseToDense(datas[0], datas[1], flow);
    /*
    for (int i = 2; i < datas.size(); i++) {
        Flow flow2;
        cv::calcOpticalFlowFarneback(datas[i-1], datas[i], flow2, 0.3, 20, 70, 2, 7, 1.7, cv::OPTFLOW_FARNEBACK_GAUSSIAN);
        flow += flow2;
    }
    */

    std::vector<cv::Point2f> features(1000, {-1, -1});
    features.resize(1000, {-1, -1});
    cv::goodFeaturesToTrack(datas[0], features, 1000, 0.01, 30);

    std::vector<cv::Point2f> features2(1000, {-1, -1});
    std::vector<uchar> status(1000, 0);
    std::vector<float> err(1000, 0);
    cv::calcOpticalFlowPyrLK(datas[0], datas[1], features, features2, status, err);

    for (int i = 0; i < features.size(); i++) {
        std::cout << features[i] << " " << features2[i] << " " << (int)status[i] << " " << err[i] << std::endl;
        const auto& f = features[i];
        if (status[i])
            datas[0](f.y, f.x) = TYPE_UNKNOWN;
        else
            datas[0](f.y, f.x) = TYPE_NO_DATA;
        //datas[0](f.y+1, f.x) = TYPE_UNKNOWN;
        //datas[0](f.y, f.x+1) = TYPE_UNKNOWN;
        //datas[0](f.y+1, f.x+1) = TYPE_UNKNOWN;
    }

    colorize(datas, "test%02d");
    //colorize(flow, "test");

    return 0;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	ディレクトリー・クラス（ヘッダー）
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <pthread.h>
#include <semaphore.h>
#include <string>
#include "utils/drive_info.hpp"
#include "utils/file_info.hpp"
#include "utils/string_utils.hpp"
#include "utils/handle_set.hpp"

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	ディレクトリー・クラス@n
				ディレクトリー情報を格納
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class files {
	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	パス・タスク構造体
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct files_io {
			pthread_t	pth_t_;
			sem_t	start_;
			sem_t	send_;
			sem_t	recv_;

			std::string	path_;
			std::string	exts_;

			file_infos	file_infos_;

			volatile bool	exit_;

			bool set_path(const std::string& path, const std::string& exts) {
				if(path.empty()) return false;
				path_ = path;
				exts_ = exts;
				return true;
			}
			files_io() : exit_(false) { }
		};

	private:
		files_io   	files_io_;

		file_infos	file_infos_;

		bool	start_;

		void init_task_();
		void destroy_task_();
	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
			@param[in]	path	パス
		*/
		//-----------------------------------------------------------------//
		files() : start_(false) { init_task_(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-----------------------------------------------------------------//
		~files() { destroy_task_(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	ルートパスを設定
			@param[in]	path	パス
			@param[in]	ext		拡張子フィルター
		*/
		//-----------------------------------------------------------------//
		void set_path(const std::string& path, const std::string& ext = "") {
			if(!start_) {
				sem_wait(&files_io_.start_);
				start_ = true;
			}
			if(files_io_.set_path(path, ext)) {
				sem_post(&files_io_.recv_);
				file_infos_.clear();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	ファイル情報取得かどうか？
			@return ファイル情報取得なら「true」
		*/
		//-----------------------------------------------------------------//
		bool probe();

		//-----------------------------------------------------------------//
		/*!
			@brief	ファイル情報郡を取得
			@return ファイル情報郡
		*/
		//-----------------------------------------------------------------//
		const file_infos& get();
	};

}
<commit_msg>パス、拡張子、取得のメソッドの追加<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	ディレクトリー・クラス（ヘッダー）
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <pthread.h>
#include <semaphore.h>
#include <string>
#include "utils/drive_info.hpp"
#include "utils/file_info.hpp"
#include "utils/string_utils.hpp"
#include "utils/handle_set.hpp"

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	ディレクトリー・クラス@n
				ディレクトリー情報を格納
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class files {
	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	パス・タスク構造体
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct files_io {
			pthread_t	pth_t_;
			sem_t	start_;
			sem_t	send_;
			sem_t	recv_;

			std::string	path_;
			std::string	exts_;

			file_infos	file_infos_;

			volatile bool	exit_;

			bool set_path(const std::string& path, const std::string& exts) {
				if(path.empty()) return false;
				path_ = path;
				exts_ = exts;
				return true;
			}
			const std::string& get_path() const { return path_; }
			const std::string& get_exts() const { return exts_; }
			files_io() : exit_(false) { }
		};

	private:
		files_io   	files_io_;

		file_infos	file_infos_;

		bool	start_;

		void init_task_();
		void destroy_task_();
	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
			@param[in]	path	パス
		*/
		//-----------------------------------------------------------------//
		files() : start_(false) { init_task_(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-----------------------------------------------------------------//
		~files() { destroy_task_(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	ルートパスを設定
			@param[in]	path	パス
			@param[in]	ext		拡張子フィルター
		*/
		//-----------------------------------------------------------------//
		void set_path(const std::string& path, const std::string& ext = "") {
			if(!start_) {
				sem_wait(&files_io_.start_);
				start_ = true;
			}
			if(files_io_.set_path(path, ext)) {
				sem_post(&files_io_.recv_);
				file_infos_.clear();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	ルートパスを取得
			@return ルートパス
		*/
		//-----------------------------------------------------------------//
		const std::string& get_path() const { return files_io_.get_path(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	拡張子を取得
			@return 拡張子
		*/
		//-----------------------------------------------------------------//
		const std::string& get_exts() const { return files_io_.get_exts(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	ファイル情報取得かどうか？
			@return ファイル情報取得なら「true」
		*/
		//-----------------------------------------------------------------//
		bool probe();

		//-----------------------------------------------------------------//
		/*!
			@brief	ファイル情報郡を取得
			@return ファイル情報郡
		*/
		//-----------------------------------------------------------------//
		const file_infos& get();
	};

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fltrcfg.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-01-19 18:33:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SVT_FLTRCFG_HXX
#define _SVT_FLTRCFG_HXX

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

#ifndef INCLUDED_SVLDLLAPI_H
#include "svtools/svldllapi.h"
#endif

#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

struct SvtFilterOptions_Impl;
class SVL_DLLPUBLIC SvtFilterOptions : public utl::ConfigItem
{
    SvtFilterOptions_Impl* pImp;

    const com::sun::star::uno::Sequence<rtl::OUString>& GetPropertyNames();
public:
                    SvtFilterOptions();
    virtual        ~SvtFilterOptions();

    virtual void            Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames);
    virtual void            Commit();
    void                    Load();

    void SetLoadWordBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicCode() const;
    void SetLoadWordBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicStorage() const;

    void SetLoadExcelBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicCode() const;
    void SetLoadExcelBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicStorage() const;

    void SetLoadPPointBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicCode() const;
    void SetLoadPPointBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicStorage() const;

    sal_Bool IsMathType2Math() const;
    void SetMathType2Math( sal_Bool bFlag );
    sal_Bool IsMath2MathType() const;
    void SetMath2MathType( sal_Bool bFlag );

    sal_Bool IsWinWord2Writer() const;
    void SetWinWord2Writer( sal_Bool bFlag );
    sal_Bool IsWriter2WinWord() const;
    void SetWriter2WinWord( sal_Bool bFlag );

    sal_Bool IsExcel2Calc() const;
    void SetExcel2Calc( sal_Bool bFlag );
    sal_Bool IsCalc2Excel() const;
    void SetCalc2Excel( sal_Bool bFlag );

    sal_Bool IsPowerPoint2Impress() const;
    void SetPowerPoint2Impress( sal_Bool bFlag );
    sal_Bool IsImpress2PowerPoint() const;
    void SetImpress2PowerPoint( sal_Bool bFlag );

    static SvtFilterOptions* Get();
};

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.5.668); FILE MERGED 2008/04/01 15:44:20 thb 1.5.668.3: #i85898# Stripping all external header guards 2008/04/01 12:43:06 thb 1.5.668.2: #i85898# Stripping all external header guards 2008/03/31 13:00:50 rt 1.5.668.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: fltrcfg.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SVT_FLTRCFG_HXX
#define _SVT_FLTRCFG_HXX

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

#include "svtools/svldllapi.h"
#include <unotools/configitem.hxx>

struct SvtFilterOptions_Impl;
class SVL_DLLPUBLIC SvtFilterOptions : public utl::ConfigItem
{
    SvtFilterOptions_Impl* pImp;

    const com::sun::star::uno::Sequence<rtl::OUString>& GetPropertyNames();
public:
                    SvtFilterOptions();
    virtual        ~SvtFilterOptions();

    virtual void            Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames);
    virtual void            Commit();
    void                    Load();

    void SetLoadWordBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicCode() const;
    void SetLoadWordBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadWordBasicStorage() const;

    void SetLoadExcelBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicCode() const;
    void SetLoadExcelBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadExcelBasicStorage() const;

    void SetLoadPPointBasicCode( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicCode() const;
    void SetLoadPPointBasicStorage( sal_Bool bFlag );
    sal_Bool IsLoadPPointBasicStorage() const;

    sal_Bool IsMathType2Math() const;
    void SetMathType2Math( sal_Bool bFlag );
    sal_Bool IsMath2MathType() const;
    void SetMath2MathType( sal_Bool bFlag );

    sal_Bool IsWinWord2Writer() const;
    void SetWinWord2Writer( sal_Bool bFlag );
    sal_Bool IsWriter2WinWord() const;
    void SetWriter2WinWord( sal_Bool bFlag );

    sal_Bool IsExcel2Calc() const;
    void SetExcel2Calc( sal_Bool bFlag );
    sal_Bool IsCalc2Excel() const;
    void SetCalc2Excel( sal_Bool bFlag );

    sal_Bool IsPowerPoint2Impress() const;
    void SetPowerPoint2Impress( sal_Bool bFlag );
    sal_Bool IsImpress2PowerPoint() const;
    void SetImpress2PowerPoint( sal_Bool bFlag );

    static SvtFilterOptions* Get();
};

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xbmread.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:18:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XBMREAD_HXX
#define _XBMREAD_HXX

#ifndef _GRAPH_HXX
#include <vcl/graph.hxx>
#endif
#ifndef _BMPACC_HXX
#include <vcl/bmpacc.hxx>
#endif

#ifdef _XBMPRIVATE

// ---------
// - Enums -
// ---------

enum XBMFormat
{
    XBM10,
    XBM11
};

enum ReadState
{
    XBMREAD_OK,
    XBMREAD_ERROR,
    XBMREAD_NEED_MORE
};

// -------------
// - XBMReader -
// -------------

class XBMReader : public GraphicReader
{
    SvStream&           rIStm;
    Bitmap              aBmp1;
    BitmapWriteAccess*  pAcc1;
    short*              pHexTable;
    BitmapColor         aWhite;
    BitmapColor         aBlack;
    long                nLastPos;
    long                nWidth;
    long                nHeight;
    BOOL                bStatus;

    void                InitTable();
    ByteString          FindTokenLine( SvStream* pInStm, const char* pTok1,
                                       const char* pTok2 = NULL, const char* pTok3 = NULL );
    long                ParseDefine( const sal_Char* pDefine );
    BOOL                ParseData( SvStream* pInStm, const ByteString& aLastLine, XBMFormat eFormat );

public:

                        XBMReader( SvStream& rStm, void* pCallData );
    virtual             ~XBMReader();

    ReadState           ReadXBM( Graphic& rGraphic );
};

#endif // _XBMPRIVATE

// -------------
// - ImportXBM -
// -------------

BOOL ImportXBM( SvStream& rStream, Graphic& rGraphic, void* pCallerData );

#endif // _XBMREAD_HXX
<commit_msg>INTEGRATION: CWS aw024 (1.2.1068); FILE MERGED 2005/09/19 18:27:34 aw 1.2.1068.2: RESYNC: (1.2-1.3); FILE MERGED 2005/08/04 15:37:39 sj 1.2.1068.1: #48467# using GraphicExporter component for exports, graphic filter progress now works now via xStatusIndicater instead of callback mechanism<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xbmread.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: ihi $ $Date: 2006-11-14 15:39:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XBMREAD_HXX
#define _XBMREAD_HXX

#ifndef _GRAPH_HXX
#include <vcl/graph.hxx>
#endif
#ifndef _BMPACC_HXX
#include <vcl/bmpacc.hxx>
#endif

#ifdef _XBMPRIVATE

// ---------
// - Enums -
// ---------

enum XBMFormat
{
    XBM10,
    XBM11
};

enum ReadState
{
    XBMREAD_OK,
    XBMREAD_ERROR,
    XBMREAD_NEED_MORE
};

// -------------
// - XBMReader -
// -------------

class XBMReader : public GraphicReader
{
    SvStream&           rIStm;
    Bitmap              aBmp1;
    BitmapWriteAccess*  pAcc1;
    short*              pHexTable;
    BitmapColor         aWhite;
    BitmapColor         aBlack;
    long                nLastPos;
    long                nWidth;
    long                nHeight;
    BOOL                bStatus;

    void                InitTable();
    ByteString          FindTokenLine( SvStream* pInStm, const char* pTok1,
                                       const char* pTok2 = NULL, const char* pTok3 = NULL );
    long                ParseDefine( const sal_Char* pDefine );
    BOOL                ParseData( SvStream* pInStm, const ByteString& aLastLine, XBMFormat eFormat );

public:

                        XBMReader( SvStream& rStm );
    virtual             ~XBMReader();

    ReadState           ReadXBM( Graphic& rGraphic );
};

#endif // _XBMPRIVATE

// -------------
// - ImportXBM -
// -------------

BOOL ImportXBM( SvStream& rStream, Graphic& rGraphic );

#endif // _XBMREAD_HXX
<|endoftext|>


<commit_before>// -*- Mode: c++-mode; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
//
// Copyright (C) 2004 Grzegorz Jaskiewicz <gj at pointblue.com.pl>
//
// gadurichtextformat.cpp
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.

#include <kopetenotifyclient.h>
#include <kdebug.h>
#include <kopetemessage.h>

#include "gadurichtextformat.h"
#include "gadusession.h"

#include <qstring.h>
#include <qregexp.h>

GaduRichTextFormat::GaduRichTextFormat()
{
}

GaduRichTextFormat::~GaduRichTextFormat()
{
}

QString
GaduRichTextFormat::convertToHtml( const QString& msg, unsigned int formats, void* formatStructure)
{
	QString tmp, nb;
	gg_msg_richtext_format *format;
	char *pointer = (char*) formatStructure;

	unsigned int i,j;
	int r, g, b;
	r = g = b = 0;
	bool opened = false;

	if ( formatStructure == NULL || formats == 0 ) {
		tmp = msg;
		escapeBody( tmp );
		kdDebug(14100) << "no rtf structure, plain message\n----------------------\n" << tmp << "\n----------------------"  << endl;
		return tmp;
	}

	for ( i = 0, j = 0 ; i < formats ; ) {
		format = (gg_msg_richtext_format*) pointer;
		unsigned int position = format->position;
		char font = format->font;
		QString style;

		if ( position < j || position > msg.length() ) {
			break;
		}

		if ( font & GG_FONT_IMAGE ) {
			i += sizeof( gg_msg_richtext_image );
			pointer += sizeof( gg_msg_richtext_image );
			tmp += "[this should be a picture, not yet implemented]";
		}
		else {
			nb = msg.mid( j, position - j );
			tmp += escapeBody( nb );

			j = position;

			// add message bit between formating
			if ( opened ) {
				tmp += formatClosingTag("span");
				opened = false;
			}
			// set font attributes
			if ( font & GG_FONT_BOLD ) {
				style += (" font-weight:bold; ");
			}
			if ( font & GG_FONT_ITALIC ) {
				style += (" font-style:italic; ");
			}
			if ( font & GG_FONT_UNDERLINE ) {
				style += (" text-decoration:underline; ");
			}
			// add color
			if ( font & GG_FONT_COLOR ) {
				pointer += sizeof( gg_msg_richtext_format );
				i += sizeof( gg_msg_richtext_format );
				gg_msg_richtext_color *color = (gg_msg_richtext_color*)( pointer );
				r = (int)color->red;
				g = (int)color->green;
				b = (int)color->blue;
			}
			style += QString(" color: rgb( %1, %2, %3 ); ").arg( r ).arg( g ).arg( b );

			kdDebug(14100) << "escape and add: \n----------------------\n" << nb << "\n----------------------" << endl;

			tmp += formatOpeningTag( QString::fromLatin1("span"), QString::fromLatin1("style=\"%1\"").arg( style ) );
			opened = true;

		}

		// advance to next structure in row
		pointer += sizeof( gg_msg_richtext_format );
		i += sizeof( gg_msg_richtext_format );
	}

	nb = msg.mid( j, msg.length() );
	tmp += escapeBody( nb );
	if ( opened ) {
		tmp += formatClosingTag("span");
	}

	kdDebug(14100) << "----------\n" << tmp << "\n----------" << endl;

	return tmp;
}

QString
GaduRichTextFormat::formatOpeningTag( const QString& tag, const QString& attributes )
{
	QString res = "<" + tag;
	if(!attributes.isEmpty())
		res.append(" " + attributes);
	return res + ">";
}

QString
GaduRichTextFormat::formatClosingTag( const QString& tag )
{
	return "</" + tag + ">";
}

// the initial idea stolen from IRC plugin
KGaduMessage*
GaduRichTextFormat::convertToGaduMessage( const KopeteMessage& message )
{
	QString htmlString = message.escapedBody();
kdDebug(14100) << "-------------------------\n" << htmlString << "\n------------------"<<endl;
	KGaduMessage* output = new KGaduMessage;
	rtcs.blue  = rtcs.green = rtcs.red = 0;
	color = QColor();
	int position = 0;

	rtf.resize( sizeof( gg_msg_richtext) );
	output->rtf.resize(0);

	// test first if there is any HTML formating in it
	if( htmlString.find( QString::fromLatin1(" -1 ) {
		QRegExp findTags( QString::fromLatin1("(.*)") );
		findTags.setMinimal( true );
		int pos = 0;
		int lastpos = 0;

		while ( pos >= 0 ){
			pos = findTags.search( htmlString );
			rtfs.font = 0;
			kdDebug( 14100 ) << "pos: " << pos <<", lastpos: " << lastpos << endl;
			if ( pos != lastpos ) {
				QString tmp;
				if ( pos < 0 ) {
					tmp = htmlString.mid( lastpos );
				}
				else {
					tmp = htmlString.mid( lastpos, pos - lastpos );
				}
				if ( !tmp.isEmpty() ) {
					color.setRgb( 0, 0, 0 );
					if ( insertRtf( position ) == false ) {
						delete output;
						return NULL;
					}
					tmp = unescapeGaduMessage( tmp );
					output->message += tmp;
					position += tmp.length();
					kdDebug(14100) << "text between without encoding I reckon \"" << tmp << "\"" << endl;
				}
			}

			if ( pos > -1 ) {
				QString styleHTML = findTags.cap(1);
				QString replacement = findTags.cap(2);
				QStringList styleAttrs = QStringList::split( ';', styleHTML );
				rtfs.font = 0;

				lastpos = pos + replacement.length();

				kdDebug(14100) << "\nposition : " << pos << endl;
				kdDebug(14100)  <<"--------------\nstyle: "  << endl;
				for( QStringList::Iterator attrPair = styleAttrs.begin(); attrPair != styleAttrs.end(); ++attrPair ) {
					QString attribute = (*attrPair).section(':',0,0);
					QString value = (*attrPair).section(':',1);
					parseAttributes( attribute, value );
				}

				if ( insertRtf( position ) == false ) {
					delete output;
					return NULL;
				}

				QString rep = QString("%2" ).arg( styleHTML ).arg( replacement );
				htmlString.replace( findTags.pos( 0 ), rep.length(), replacement );

				replacement = unescapeGaduMessage( replacement );
				kdDebug(14100) << " message: \"" <<replacement <<"\"\n---------------" << endl;
				output->message += replacement;
				position += replacement.length();
			}

		}
		output->rtf = rtf;
		// this is sick, but that's the way libgadu is designed
		// here I am adding network header !, should sit in libgadu IMO
		header = (gg_msg_richtext*) output->rtf.data();
		header->length = output->rtf.size() - sizeof( gg_msg_richtext );
		header->flag = 2;
	}
	else {
		output->message = message.escapedBody();
		output->message = unescapeGaduMessage( output->message );
	}

	return output;

}

void
GaduRichTextFormat::parseAttributes( const QString attribute, const QString value )
{
	if( attribute == QString::fromLatin1("color") ) {
		color.setNamedColor( value );
		kdDebug(14100) << "color detected, value: \"" <<  value << "\"  " << endl;
	}
	if( attribute == QString::fromLatin1("font-weight") && value == QString::fromLatin1("600") ) {
		kdDebug(14100) << " font bold " << endl;
		rtfs.font |= GG_FONT_BOLD;
	}
	if( attribute == QString::fromLatin1("text-decoration")  && value == QString::fromLatin1("underline") ) {
		kdDebug(14100) << " font underline "  << endl;
		rtfs.font |= GG_FONT_UNDERLINE ;
	}
	if( attribute == QString::fromLatin1("font-style")  && value == QString::fromLatin1("italic") ) {
		kdDebug(14100) << " font italic "  << endl;
		rtfs.font |= GG_FONT_ITALIC;
	}
}

QString
GaduRichTextFormat::unescapeGaduMessage( QString& ns )
{
	QString s;
	s = KopeteMessage::unescape( ns );
	s.replace( QString::fromAscii( "\n" ), QString::fromAscii( "\r\n" ) );
	return s;
}

bool
GaduRichTextFormat::insertRtf( uint position)
{
	if ( color != QColor( rtcs.red, rtcs.green, rtcs.blue ) ) {
		rtcs.red   = color.red();
		rtcs.green = color.green();
		rtcs.blue  = color.blue();
		rtfs.font |= GG_FONT_COLOR;
	}

	if ( rtfs.font ) {
		// append font description
		rtfs.position = position;
		uint csize = rtf.size();
		if ( rtf.resize( csize + sizeof( gg_msg_richtext_format ) ) == FALSE ) {
			kdDebug( 14100 ) << "problem allocating memory, message cannot be sent" << endl;
			return false;
		};
		memcpy( rtf.data()  + csize, &rtfs, sizeof( rtfs ) );
		// append color description, if color has changed
		if ( rtfs.font & GG_FONT_COLOR ) {
			csize = rtf.size();
			if ( rtf.resize( csize + sizeof( gg_msg_richtext_color ) ) == FALSE ) {
				kdDebug( 14100 ) << "problem allocating memory, message cannot be sent" << endl;
				return false;
			};
			memcpy( rtf.data() + csize, &rtcs, sizeof( rtcs ) );
		}
	}
	return true;
}

QString
GaduRichTextFormat::escapeBody( QString& input )
{
	input.replace( '\n', QString::fromLatin1( "
" ) );
	input.replace( '\t', QString::fromLatin1( "    " ) );
	input.replace( QRegExp( QString::fromLatin1( "\\s\\s" ) ), QString::fromLatin1( "  " ) );
	input.replace( '<', QString::fromLatin1("<") );
	input.replace( '>', QString::fromLatin1(">") );
	return input;
}
<commit_msg>CVS_SILENT remove debug messages<commit_after>// -*- Mode: c++-mode; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
//
// Copyright (C) 2004 Grzegorz Jaskiewicz <gj at pointblue.com.pl>
//
// gadurichtextformat.cpp
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.

#include <kopetenotifyclient.h>
#include <kdebug.h>
#include <kopetemessage.h>

#include "gadurichtextformat.h"
#include "gadusession.h"

#include <qstring.h>
#include <qregexp.h>

GaduRichTextFormat::GaduRichTextFormat()
{
}

GaduRichTextFormat::~GaduRichTextFormat()
{
}

QString
GaduRichTextFormat::convertToHtml( const QString& msg, unsigned int formats, void* formatStructure)
{
	QString tmp, nb;
	gg_msg_richtext_format *format;
	char *pointer = (char*) formatStructure;

	unsigned int i,j;
	int r, g, b;
	r = g = b = 0;
	bool opened = false;

	if ( formatStructure == NULL || formats == 0 ) {
		tmp = msg;
		escapeBody( tmp );
		return tmp;
	}

	for ( i = 0, j = 0 ; i < formats ; ) {
		format = (gg_msg_richtext_format*) pointer;
		unsigned int position = format->position;
		char font = format->font;
		QString style;

		if ( position < j || position > msg.length() ) {
			break;
		}

		if ( font & GG_FONT_IMAGE ) {
			i += sizeof( gg_msg_richtext_image );
			pointer += sizeof( gg_msg_richtext_image );
			tmp += "[this should be a picture, not yet implemented]";
		}
		else {
			nb = msg.mid( j, position - j );
			tmp += escapeBody( nb );

			j = position;

			// add message bit between formating
			if ( opened ) {
				tmp += formatClosingTag("span");
				opened = false;
			}
			// set font attributes
			if ( font & GG_FONT_BOLD ) {
				style += (" font-weight:bold; ");
			}
			if ( font & GG_FONT_ITALIC ) {
				style += (" font-style:italic; ");
			}
			if ( font & GG_FONT_UNDERLINE ) {
				style += (" text-decoration:underline; ");
			}
			// add color
			if ( font & GG_FONT_COLOR ) {
				pointer += sizeof( gg_msg_richtext_format );
				i += sizeof( gg_msg_richtext_format );
				gg_msg_richtext_color *color = (gg_msg_richtext_color*)( pointer );
				r = (int)color->red;
				g = (int)color->green;
				b = (int)color->blue;
			}
			style += QString(" color: rgb( %1, %2, %3 ); ").arg( r ).arg( g ).arg( b );

			tmp += formatOpeningTag( QString::fromLatin1("span"), QString::fromLatin1("style=\"%1\"").arg( style ) );
			opened = true;

		}

		// advance to next structure in row
		pointer += sizeof( gg_msg_richtext_format );
		i += sizeof( gg_msg_richtext_format );
	}

	nb = msg.mid( j, msg.length() );
	tmp += escapeBody( nb );
	if ( opened ) {
		tmp += formatClosingTag("span");
	}

	return tmp;
}

QString
GaduRichTextFormat::formatOpeningTag( const QString& tag, const QString& attributes )
{
	QString res = "<" + tag;
	if(!attributes.isEmpty())
		res.append(" " + attributes);
	return res + ">";
}

QString
GaduRichTextFormat::formatClosingTag( const QString& tag )
{
	return "</" + tag + ">";
}

// the initial idea stolen from IRC plugin
KGaduMessage*
GaduRichTextFormat::convertToGaduMessage( const KopeteMessage& message )
{
	QString htmlString = message.escapedBody();
	KGaduMessage* output = new KGaduMessage;
	rtcs.blue  = rtcs.green = rtcs.red = 0;
	color = QColor();
	int position = 0;

	rtf.resize( sizeof( gg_msg_richtext) );
	output->rtf.resize(0);

	// test first if there is any HTML formating in it
	if( htmlString.find( QString::fromLatin1(" -1 ) {
		QRegExp findTags( QString::fromLatin1("(.*)") );
		findTags.setMinimal( true );
		int pos = 0;
		int lastpos = 0;

		while ( pos >= 0 ){
			pos = findTags.search( htmlString );
			rtfs.font = 0;
			if ( pos != lastpos ) {
				QString tmp;
				if ( pos < 0 ) {
					tmp = htmlString.mid( lastpos );
				}
				else {
					tmp = htmlString.mid( lastpos, pos - lastpos );
				}
				if ( !tmp.isEmpty() ) {
					color.setRgb( 0, 0, 0 );
					if ( insertRtf( position ) == false ) {
						delete output;
						return NULL;
					}
					tmp = unescapeGaduMessage( tmp );
					output->message += tmp;
					position += tmp.length();
				}
			}

			if ( pos > -1 ) {
				QString styleHTML = findTags.cap(1);
				QString replacement = findTags.cap(2);
				QStringList styleAttrs = QStringList::split( ';', styleHTML );
				rtfs.font = 0;

				lastpos = pos + replacement.length();

				for( QStringList::Iterator attrPair = styleAttrs.begin(); attrPair != styleAttrs.end(); ++attrPair ) {
					QString attribute = (*attrPair).section(':',0,0);
					QString value = (*attrPair).section(':',1);
					parseAttributes( attribute, value );
				}

				if ( insertRtf( position ) == false ) {
					delete output;
					return NULL;
				}

				QString rep = QString("%2" ).arg( styleHTML ).arg( replacement );
				htmlString.replace( findTags.pos( 0 ), rep.length(), replacement );

				replacement = unescapeGaduMessage( replacement );
				output->message += replacement;
				position += replacement.length();
			}

		}
		output->rtf = rtf;
		// this is sick, but that's the way libgadu is designed
		// here I am adding network header !, should sit in libgadu IMO
		header = (gg_msg_richtext*) output->rtf.data();
		header->length = output->rtf.size() - sizeof( gg_msg_richtext );
		header->flag = 2;
	}
	else {
		output->message = message.escapedBody();
		output->message = unescapeGaduMessage( output->message );
	}

	return output;

}

void
GaduRichTextFormat::parseAttributes( const QString attribute, const QString value )
{
	if( attribute == QString::fromLatin1("color") ) {
		color.setNamedColor( value );
	}
	if( attribute == QString::fromLatin1("font-weight") && value == QString::fromLatin1("600") ) {
		rtfs.font |= GG_FONT_BOLD;
	}
	if( attribute == QString::fromLatin1("text-decoration")  && value == QString::fromLatin1("underline") ) {
		rtfs.font |= GG_FONT_UNDERLINE ;
	}
	if( attribute == QString::fromLatin1("font-style")  && value == QString::fromLatin1("italic") ) {
		rtfs.font |= GG_FONT_ITALIC;
	}
}

QString
GaduRichTextFormat::unescapeGaduMessage( QString& ns )
{
	QString s;
	s = KopeteMessage::unescape( ns );
	s.replace( QString::fromAscii( "\n" ), QString::fromAscii( "\r\n" ) );
	return s;
}

bool
GaduRichTextFormat::insertRtf( uint position)
{
	if ( color != QColor( rtcs.red, rtcs.green, rtcs.blue ) ) {
		rtcs.red   = color.red();
		rtcs.green = color.green();
		rtcs.blue  = color.blue();
		rtfs.font |= GG_FONT_COLOR;
	}

	if ( rtfs.font ) {
		// append font description
		rtfs.position = position;
		uint csize = rtf.size();
		if ( rtf.resize( csize + sizeof( gg_msg_richtext_format ) ) == FALSE ) {
			return false;
		};
		memcpy( rtf.data()  + csize, &rtfs, sizeof( rtfs ) );
		// append color description, if color has changed
		if ( rtfs.font & GG_FONT_COLOR ) {
			csize = rtf.size();
			if ( rtf.resize( csize + sizeof( gg_msg_richtext_color ) ) == FALSE ) {
				return false;
			};
			memcpy( rtf.data() + csize, &rtcs, sizeof( rtcs ) );
		}
	}
	return true;
}

QString
GaduRichTextFormat::escapeBody( QString& input )
{
	input.replace( '\n', QString::fromLatin1( "
" ) );
	input.replace( '\t', QString::fromLatin1( "    " ) );
	input.replace( QRegExp( QString::fromLatin1( "\\s\\s" ) ), QString::fromLatin1( "  " ) );
	input.replace( '<', QString::fromLatin1("<") );
	input.replace( '>', QString::fromLatin1(">") );
	return input;
}
<|endoftext|>