<commit_before>#include "union_storage.h"
#include "storage/memstorage.h"
#include "storage/capacitor.h"
#include "utils/exception.h"
#include "utils/locker.h"
#include "storage/page_manager.h"
#include <cassert>
#include <algorithm>

using namespace dariadb;
using namespace dariadb::storage;

class UnionStorage::Private {
public:
	Private(const PageManager::Params&page_storage_params,
		dariadb::storage::Capacitor::Params cap_params,
		dariadb::storage::UnionStorage::Limits limits) :
		mem_storage{ new MemoryStorage(page_storage_params.chunk_size) },
		_page_manager_params(page_storage_params),
		_cap_params(cap_params),
       _limits(limits)
	{
		dariadb::storage::ChunkPool::instance()->start(_limits.max_mem_chunks);

		mem_cap = new Capacitor(mem_storage, _cap_params);
		mem_storage_raw = dynamic_cast<MemoryStorage*>(mem_storage.get());
		assert(mem_storage_raw != nullptr);

		PageManager::start(_page_manager_params);

		auto open_chunks = PageManager::instance()->get_open_chunks();
        mem_storage_raw->append(open_chunks);
        mem_storage_raw->set_chunkWriter(PageManager::instance());
	}
	~Private() {
		this->flush();
        if (_limits.max_mem_chunks != 0) {
            auto all_chunks = this->mem_storage_raw->drop_all();
            PageManager::instance()->append(all_chunks); //use specified in ctor
        }
		delete mem_cap;
		PageManager::stop();

	}

	Time minTime() {
        std::lock_guard<std::recursive_mutex> lg(_locker);
        if(PageManager::instance()->chunks_in_cur_page()>0){
            return PageManager::instance()->minTime();
        }else{
            return mem_storage->minTime();
        }
	}

	Time maxTime() {
		return mem_storage->maxTime();
	}

	append_result append(const Meas::PMeas begin, const size_t size) {
		append_result result{};
		for (size_t i = 0; i < size; i++) {
			result = result + this->append(begin[i]);
		}
		return result;
	}

	append_result append(const Meas &value) {
		append_result result{};
        if (!mem_cap->append(value)){
        //if(mem_storage_raw->append(value).writed!=1){
            assert(false);
			result.ignored++;
		}
		else {
			result.writed++;
		}

        drop_old_chunks();
		return result;
	}

	void drop_old_chunks() {
		if (_limits.max_mem_chunks == 0) {
			if (_limits.old_mem_chunks != 0) {
				auto old_chunks = mem_storage_raw->drop_old_chunks(_limits.old_mem_chunks);
                //PageManager::instance()->append(old_chunks);
			}
		}
		else {
			auto old_chunks = mem_storage_raw->drop_old_chunks_by_limit(_limits.max_mem_chunks);
#ifdef DEBUG
            for(auto c:old_chunks){
                assert(c->_buffer_t.size()!=0);
            }
#endif
            //PageManager::instance()->append(old_chunks);
		}
	}

	void subscribe(const IdArray&ids, const Flag& flag, const ReaderClb_ptr &clbk) {
		mem_storage->subscribe(ids, flag, clbk);
	}

	Reader_ptr currentValue(const IdArray&ids, const Flag& flag) {
		return mem_storage->currentValue(ids, flag);
	}

	void flush() {
        std::lock_guard<std::recursive_mutex> lg(_locker);
		this->mem_cap->flush();
		this->drop_old_chunks();
		PageManager::instance()->flush();
	}

	UnionStorage::QueueSizes queue_size() const {
		QueueSizes result;
		result.page = PageManager::instance()->in_queue_size();
		result.mem = this->mem_storage_raw->queue_size();
		result.cap = this->mem_cap->size();
		return result;
	}

	class UnionCursor : public Cursor {
	public:
		Cursor_ptr _page_cursor;
		Cursor_ptr _mem_cursor;
		UnionCursor(Cursor_ptr &page_cursor, Cursor_ptr&mem_cursor):
			_page_cursor{page_cursor},
			_mem_cursor(mem_cursor)
		{
			this->reset_pos();
		}
		~UnionCursor() {
			_page_cursor = nullptr;
			_mem_cursor = nullptr;
		}

		bool is_end()const override {
			return
				(_page_cursor==nullptr?true:_page_cursor->is_end())
				&& (_mem_cursor==nullptr?true:_mem_cursor->is_end());
		}

		void readNext(Cursor::Callback*cbk)  override
		{
			if (!is_end()) {
				if ((_page_cursor!=nullptr) && (!_page_cursor->is_end())) {
					_page_cursor->readNext(cbk);
					return;
				}
				else
				{
					if ((_mem_cursor!=nullptr)&&(!_mem_cursor->is_end())) {
						_mem_cursor->readNext(cbk);
						return;
					}
				}
			}
		}

		void reset_pos() override {
			if (_page_cursor != nullptr) {
				_page_cursor->reset_pos();
			}
			if (_mem_cursor != nullptr) {
				_mem_cursor->reset_pos();
			}
		}
	};

	class UnionCursorSet : public Cursor {
	public:
		CursorList _cursors;
		CursorList::iterator it;
		bool _is_end;
		UnionCursorSet() {
		}
		~UnionCursorSet() {
			_cursors.clear();
		}

		void add_cursor(const Cursor_ptr &cptr) {
			_cursors.push_back(cptr);
			reset_pos();
		}

		bool is_end()const override {
			return _is_end;
		}

		void readNext(Cursor::Callback*cbk)  override {
			if (it == _cursors.end()) {
				_is_end = true;
                Chunk_Ptr empty;
                cbk->call(empty);
                return;
			}
			else {
				Cursor_ptr c = *it;
				if (c->is_end()) {//TODO refact.
					if (it == _cursors.end()) {
						_is_end = true;
						Chunk_Ptr empty;
						cbk->call(empty);
						return;
					}
					else {
						++it;
					}
				}
                if(it!=_cursors.end()){
                    c = *it;
                    c->readNext(cbk);
                }
			}
			if (_is_end) {
				Chunk_Ptr empty;
				cbk->call(empty);
			}
		}

		void reset_pos() override {
			it = _cursors.begin();
			_is_end = false;
			for (auto&c : _cursors) {
				c->reset_pos();
			}
		}
	};

	Cursor_ptr chunksByIterval(const IdArray &ids, Flag flag, Time from, Time to) {
        std::lock_guard<std::recursive_mutex> lg(_locker);
		IdArray id_a = ids;
		if (id_a.empty()) {
			id_a = getIds();
		}
		UnionCursorSet *raw_result = new UnionCursorSet();
		Cursor_ptr result{ raw_result };
		for (auto id : id_a) {
			IdArray cur_ids(1);
			cur_ids[0] = id;
			Cursor_ptr page_chunks, mem_chunks;
			dariadb::Time minT, maxT;
			if (!mem_storage_raw->minMaxTime(id, &minT, &maxT)) {
				page_chunks = PageManager::instance()->chunksByIterval(cur_ids, flag, from, to);
			}
			else {
				if (minT <= from && maxT >= to) {
					mem_chunks = mem_storage_raw->chunksByIterval(cur_ids, flag, from, to);
				}
				else {
                    page_chunks = PageManager::instance()->chunksByIterval(cur_ids, flag, from, minT);
					mem_chunks = mem_storage_raw->chunksByIterval(cur_ids, flag, minT, to);
				}
			}

			Cursor_ptr sub_result{ new UnionCursor{page_chunks,mem_chunks} };
			raw_result->add_cursor(sub_result);
		}
		return result;
	}

	IdToChunkMap chunksBeforeTimePoint(const IdArray &ids, Flag flag, Time timePoint) {
        std::lock_guard<std::recursive_mutex> lg(_locker);
        IdArray id_a = ids;
        if (id_a.empty()) {
            id_a = getIds();
        }
        IdToChunkMap result;
        IdArray cur_ids{1};
        for(auto id:id_a){
            cur_ids[0]=id;
            dariadb::Time minT, maxT;
            IdToChunkMap subRes;
            if (!mem_storage_raw->minMaxTime(id, &minT, &maxT)) {
                subRes = PageManager::instance()->chunksBeforeTimePoint(cur_ids, flag, timePoint);
            }else{
                if (minT <= timePoint) {
                    subRes = mem_storage_raw->chunksBeforeTimePoint(cur_ids, flag, timePoint);
                }
                else {
                    subRes=PageManager::instance()->chunksBeforeTimePoint(cur_ids, flag, timePoint);
                }
            }
            for(auto kv:subRes){
                result[kv.first]=kv.second;
            }
        }
        return result;
	}

	bool minMaxTime(dariadb::Id id, dariadb::Time*minResult, dariadb::Time*maxResult) {
		dariadb::Time subMin1, subMax1;
		auto pr = PageManager::instance()->minMaxTime(id, &subMin1, &subMax1);
		dariadb::Time subMin2, subMax2;
		auto mr = mem_storage_raw->minMaxTime(id, &subMin2, &subMax2);

		if (!pr) {
			*minResult = subMin2;
			*maxResult = subMax2;
			return mr;
		}
		if (!mr) {
			*minResult = subMin1;
			*maxResult = subMax1;
			return pr;
		}
		*minResult = std::min(subMin1, subMin2);
		*maxResult = std::max(subMax1, subMax2);
		return true;
	}

	IdArray getIds() {
        std::lock_guard<std::recursive_mutex> lg(_locker);
		auto page_ids = PageManager::instance()->getIds();
		auto mem_ids = mem_storage_raw->getIds();
		dariadb::IdSet s;
		for (auto v : page_ids) {
			s.insert(v);
		}
		for (auto v : mem_ids) {
			s.insert(v);
		}
        return dariadb::IdArray{ s.begin(),s.end() };
	}

    size_t chunks_in_memory()const{
        std::lock_guard<std::recursive_mutex> lg(_locker);
        return mem_storage_raw->chunks_total_size();
    }

	storage::BaseStorage_ptr mem_storage;
	storage::MemoryStorage* mem_storage_raw;
	storage::Capacitor* mem_cap;

	storage::PageManager::Params _page_manager_params;
	dariadb::storage::Capacitor::Params _cap_params;
	dariadb::storage::UnionStorage::Limits _limits;
    mutable std::recursive_mutex _locker;
};

UnionStorage::UnionStorage(storage::PageManager::Params page_manager_params,
	dariadb::storage::Capacitor::Params cap_params,
    const dariadb::storage::UnionStorage::Limits&limits):
	_impl{ new UnionStorage::Private(page_manager_params,
									cap_params, limits) }
{
}

UnionStorage::~UnionStorage() {
    _impl=nullptr;
}

Time UnionStorage::minTime() {
	return _impl->minTime();
}

Time UnionStorage::maxTime() {
	return _impl->maxTime();
}

append_result UnionStorage::append(const Meas::PMeas begin, const size_t size) {
	return _impl->append(begin, size);
}

append_result UnionStorage::append(const Meas &value) {
	return _impl->append(value);
}

void UnionStorage::subscribe(const IdArray&ids, const Flag& flag, const ReaderClb_ptr &clbk) {
	_impl->subscribe(ids, flag, clbk);
}

Reader_ptr UnionStorage::currentValue(const IdArray&ids, const Flag& flag) {
	return _impl->currentValue(ids, flag);
}

void  UnionStorage::flush() {
	_impl->flush();
}

bool UnionStorage::minMaxTime(dariadb::Id id, dariadb::Time*minResult, dariadb::Time*maxResult) {
	return _impl->minMaxTime(id, minResult, maxResult);
}

Cursor_ptr UnionStorage::chunksByIterval(const IdArray &ids, Flag flag, Time from, Time to) {
	return _impl->chunksByIterval(ids, flag, from, to);
}

IdToChunkMap UnionStorage::chunksBeforeTimePoint(const IdArray &ids, Flag flag, Time timePoint) {
	return _impl->chunksBeforeTimePoint(ids, flag, timePoint);
}

IdArray UnionStorage::getIds() {
	return _impl->getIds();
}

size_t UnionStorage::chunks_in_memory()const{
    return _impl->chunks_in_memory();
}

UnionStorage::QueueSizes UnionStorage::queue_size() const{
	return  _impl->queue_size();
}
<commit_msg>async again.<commit_after>#include "union_storage.h"
#include "storage/memstorage.h"
#include "storage/capacitor.h"
#include "utils/exception.h"
#include "utils/locker.h"
#include "storage/page_manager.h"
#include <cassert>
#include <algorithm>

using namespace dariadb;
using namespace dariadb::storage;

class UnionStorage::Private {
public:
	Private(const PageManager::Params&page_storage_params,
		dariadb::storage::Capacitor::Params cap_params,
		dariadb::storage::UnionStorage::Limits limits) :
		mem_storage{ new MemoryStorage(page_storage_params.chunk_size) },
		_page_manager_params(page_storage_params),
		_cap_params(cap_params),
       _limits(limits)
	{
		dariadb::storage::ChunkPool::instance()->start(_limits.max_mem_chunks);

		mem_cap = new Capacitor(mem_storage, _cap_params);
		mem_storage_raw = dynamic_cast<MemoryStorage*>(mem_storage.get());
		assert(mem_storage_raw != nullptr);

		PageManager::start(_page_manager_params);

		auto open_chunks = PageManager::instance()->get_open_chunks();
        mem_storage_raw->append(open_chunks);
        //mem_storage_raw->set_chunkWriter(PageManager::instance());
	}
	~Private() {
		this->flush();
        if (_limits.max_mem_chunks != 0) {
            auto all_chunks = this->mem_storage_raw->drop_all();
            PageManager::instance()->append(all_chunks); //use specified in ctor
        }
		delete mem_cap;
		PageManager::stop();

	}

	Time minTime() {
        std::lock_guard<std::recursive_mutex> lg(_locker);
        if(PageManager::instance()->chunks_in_cur_page()>0){
            return PageManager::instance()->minTime();
        }else{
            return mem_storage->minTime();
        }
	}

	Time maxTime() {
		return mem_storage->maxTime();
	}

	append_result append(const Meas::PMeas begin, const size_t size) {
		append_result result{};
		for (size_t i = 0; i < size; i++) {
			result = result + this->append(begin[i]);
		}
		return result;
	}

	append_result append(const Meas &value) {
		append_result result{};
        if (!mem_cap->append(value)){
        //if(mem_storage_raw->append(value).writed!=1){
            assert(false);
			result.ignored++;
		}
		else {
			result.writed++;
		}

        drop_old_chunks();
		return result;
	}

	void drop_old_chunks() {
		if (_limits.max_mem_chunks == 0) {
			if (_limits.old_mem_chunks != 0) {
				auto old_chunks = mem_storage_raw->drop_old_chunks(_limits.old_mem_chunks);
                PageManager::instance()->append(old_chunks);
			}
		}
		else {
			auto old_chunks = mem_storage_raw->drop_old_chunks_by_limit(_limits.max_mem_chunks);
#ifdef DEBUG
            for(auto c:old_chunks){
                assert(c->_buffer_t.size()!=0);
            }
#endif
            PageManager::instance()->append(old_chunks);
		}
	}

	void subscribe(const IdArray&ids, const Flag& flag, const ReaderClb_ptr &clbk) {
		mem_storage->subscribe(ids, flag, clbk);
	}

	Reader_ptr currentValue(const IdArray&ids, const Flag& flag) {
		return mem_storage->currentValue(ids, flag);
	}

	void flush() {
        std::lock_guard<std::recursive_mutex> lg(_locker);
		this->mem_cap->flush();
		this->drop_old_chunks();
		PageManager::instance()->flush();
	}

	UnionStorage::QueueSizes queue_size() const {
		QueueSizes result;
		result.page = PageManager::instance()->in_queue_size();
		result.mem = this->mem_storage_raw->queue_size();
		result.cap = this->mem_cap->size();
		return result;
	}

	class UnionCursor : public Cursor {
	public:
		Cursor_ptr _page_cursor;
		Cursor_ptr _mem_cursor;
		UnionCursor(Cursor_ptr &page_cursor, Cursor_ptr&mem_cursor):
			_page_cursor{page_cursor},
			_mem_cursor(mem_cursor)
		{
			this->reset_pos();
		}
		~UnionCursor() {
			_page_cursor = nullptr;
			_mem_cursor = nullptr;
		}

		bool is_end()const override {
			return
				(_page_cursor==nullptr?true:_page_cursor->is_end())
				&& (_mem_cursor==nullptr?true:_mem_cursor->is_end());
		}

		void readNext(Cursor::Callback*cbk)  override
		{
			if (!is_end()) {
				if ((_page_cursor!=nullptr) && (!_page_cursor->is_end())) {
					_page_cursor->readNext(cbk);
					return;
				}
				else
				{
					if ((_mem_cursor!=nullptr)&&(!_mem_cursor->is_end())) {
						_mem_cursor->readNext(cbk);
						return;
					}
				}
			}
		}

		void reset_pos() override {
			if (_page_cursor != nullptr) {
				_page_cursor->reset_pos();
			}
			if (_mem_cursor != nullptr) {
				_mem_cursor->reset_pos();
			}
		}
	};

	class UnionCursorSet : public Cursor {
	public:
		CursorList _cursors;
		CursorList::iterator it;
		bool _is_end;
		UnionCursorSet() {
		}
		~UnionCursorSet() {
			_cursors.clear();
		}

		void add_cursor(const Cursor_ptr &cptr) {
			_cursors.push_back(cptr);
			reset_pos();
		}

		bool is_end()const override {
			return _is_end;
		}

		void readNext(Cursor::Callback*cbk)  override {
			if (it == _cursors.end()) {
				_is_end = true;
                Chunk_Ptr empty;
                cbk->call(empty);
                return;
			}
			else {
				Cursor_ptr c = *it;
				if (c->is_end()) {//TODO refact.
					if (it == _cursors.end()) {
						_is_end = true;
						Chunk_Ptr empty;
						cbk->call(empty);
						return;
					}
					else {
						++it;
					}
				}
                if(it!=_cursors.end()){
                    c = *it;
                    c->readNext(cbk);
                }
			}
			if (_is_end) {
				Chunk_Ptr empty;
				cbk->call(empty);
			}
		}

		void reset_pos() override {
			it = _cursors.begin();
			_is_end = false;
			for (auto&c : _cursors) {
				c->reset_pos();
			}
		}
	};

	Cursor_ptr chunksByIterval(const IdArray &ids, Flag flag, Time from, Time to) {
        std::lock_guard<std::recursive_mutex> lg(_locker);
		IdArray id_a = ids;
		if (id_a.empty()) {
			id_a = getIds();
		}
		UnionCursorSet *raw_result = new UnionCursorSet();
		Cursor_ptr result{ raw_result };
		for (auto id : id_a) {
			IdArray cur_ids(1);
			cur_ids[0] = id;
			Cursor_ptr page_chunks, mem_chunks;
			dariadb::Time minT, maxT;
			if (!mem_storage_raw->minMaxTime(id, &minT, &maxT)) {
				page_chunks = PageManager::instance()->chunksByIterval(cur_ids, flag, from, to);
			}
			else {
				if (minT <= from && maxT >= to) {
					mem_chunks = mem_storage_raw->chunksByIterval(cur_ids, flag, from, to);
				}
				else {
                    page_chunks = PageManager::instance()->chunksByIterval(cur_ids, flag, from, minT);
					mem_chunks = mem_storage_raw->chunksByIterval(cur_ids, flag, minT, to);
				}
			}

			Cursor_ptr sub_result{ new UnionCursor{page_chunks,mem_chunks} };
			raw_result->add_cursor(sub_result);
		}
		return result;
	}

	IdToChunkMap chunksBeforeTimePoint(const IdArray &ids, Flag flag, Time timePoint) {
        std::lock_guard<std::recursive_mutex> lg(_locker);
        IdArray id_a = ids;
        if (id_a.empty()) {
            id_a = getIds();
        }
        IdToChunkMap result;
        IdArray cur_ids{1};
        for(auto id:id_a){
            cur_ids[0]=id;
            dariadb::Time minT, maxT;
            IdToChunkMap subRes;
            if (!mem_storage_raw->minMaxTime(id, &minT, &maxT)) {
                subRes = PageManager::instance()->chunksBeforeTimePoint(cur_ids, flag, timePoint);
            }else{
                if (minT <= timePoint) {
                    subRes = mem_storage_raw->chunksBeforeTimePoint(cur_ids, flag, timePoint);
                }
                else {
                    subRes=PageManager::instance()->chunksBeforeTimePoint(cur_ids, flag, timePoint);
                }
            }
            for(auto kv:subRes){
                result[kv.first]=kv.second;
            }
        }
        return result;
	}

	bool minMaxTime(dariadb::Id id, dariadb::Time*minResult, dariadb::Time*maxResult) {
		dariadb::Time subMin1, subMax1;
		auto pr = PageManager::instance()->minMaxTime(id, &subMin1, &subMax1);
		dariadb::Time subMin2, subMax2;
		auto mr = mem_storage_raw->minMaxTime(id, &subMin2, &subMax2);

		if (!pr) {
			*minResult = subMin2;
			*maxResult = subMax2;
			return mr;
		}
		if (!mr) {
			*minResult = subMin1;
			*maxResult = subMax1;
			return pr;
		}
		*minResult = std::min(subMin1, subMin2);
		*maxResult = std::max(subMax1, subMax2);
		return true;
	}

	IdArray getIds() {
        std::lock_guard<std::recursive_mutex> lg(_locker);
		auto page_ids = PageManager::instance()->getIds();
		auto mem_ids = mem_storage_raw->getIds();
		dariadb::IdSet s;
		for (auto v : page_ids) {
			s.insert(v);
		}
		for (auto v : mem_ids) {
			s.insert(v);
		}
        return dariadb::IdArray{ s.begin(),s.end() };
	}

    size_t chunks_in_memory()const{
        std::lock_guard<std::recursive_mutex> lg(_locker);
        return mem_storage_raw->chunks_total_size();
    }

	storage::BaseStorage_ptr mem_storage;
	storage::MemoryStorage* mem_storage_raw;
	storage::Capacitor* mem_cap;

	storage::PageManager::Params _page_manager_params;
	dariadb::storage::Capacitor::Params _cap_params;
	dariadb::storage::UnionStorage::Limits _limits;
    mutable std::recursive_mutex _locker;
};

UnionStorage::UnionStorage(storage::PageManager::Params page_manager_params,
	dariadb::storage::Capacitor::Params cap_params,
    const dariadb::storage::UnionStorage::Limits&limits):
	_impl{ new UnionStorage::Private(page_manager_params,
									cap_params, limits) }
{
}

UnionStorage::~UnionStorage() {
    _impl=nullptr;
}

Time UnionStorage::minTime() {
	return _impl->minTime();
}

Time UnionStorage::maxTime() {
	return _impl->maxTime();
}

append_result UnionStorage::append(const Meas::PMeas begin, const size_t size) {
	return _impl->append(begin, size);
}

append_result UnionStorage::append(const Meas &value) {
	return _impl->append(value);
}

void UnionStorage::subscribe(const IdArray&ids, const Flag& flag, const ReaderClb_ptr &clbk) {
	_impl->subscribe(ids, flag, clbk);
}

Reader_ptr UnionStorage::currentValue(const IdArray&ids, const Flag& flag) {
	return _impl->currentValue(ids, flag);
}

void  UnionStorage::flush() {
	_impl->flush();
}

bool UnionStorage::minMaxTime(dariadb::Id id, dariadb::Time*minResult, dariadb::Time*maxResult) {
	return _impl->minMaxTime(id, minResult, maxResult);
}

Cursor_ptr UnionStorage::chunksByIterval(const IdArray &ids, Flag flag, Time from, Time to) {
	return _impl->chunksByIterval(ids, flag, from, to);
}

IdToChunkMap UnionStorage::chunksBeforeTimePoint(const IdArray &ids, Flag flag, Time timePoint) {
	return _impl->chunksBeforeTimePoint(ids, flag, timePoint);
}

IdArray UnionStorage::getIds() {
	return _impl->getIds();
}

size_t UnionStorage::chunks_in_memory()const{
    return _impl->chunks_in_memory();
}

UnionStorage::QueueSizes UnionStorage::queue_size() const{
	return  _impl->queue_size();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: FillStyleContext.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 14:23:30 $
 *
 *  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 _XMLOFF_FILLSTYLECONTEXTS_HXX_
#define _XMLOFF_FILLSTYLECONTEXTS_HXX_

#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif

#ifndef _XMLOFF_XMLSTYLE_HXX //autogen
#include <xmlstyle.hxx>
#endif

#ifndef _RTL_USTRING_
#include<rtl/ustring>
#endif

//////////////////////////////////////////////////////////////////////////////
// draw:gardient context

class XMLGradientStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLGradientStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLGradientStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:hatch context

class XMLHatchStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLHatchStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLHatchStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:fill-image context

class XMLBitmapStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > mxBase64Stream;

public:
    TYPEINFO();

    XMLBitmapStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLBitmapStyleContext();

    virtual SvXMLImportContext *CreateChildContext(
            sal_uInt16 nPrefix,
            const ::rtl::OUString& rLocalName,
            const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:transparency context

class XMLTransGradientStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLTransGradientStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLTransGradientStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:marker context

class XMLMarkerStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLMarkerStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLMarkerStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:marker context

class XMLDashStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLDashStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLDashStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

#endif  // _XMLOFF_FILLSTYLECONTEXTS_HXX_
<commit_msg>INTEGRATION: CWS warnings01 (1.4.32); FILE MERGED 2005/11/02 14:57:53 cl 1.4.32.1: warning free code changes<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: FillStyleContext.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 18:24:26 $
 *
 *  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 _XMLOFF_FILLSTYLECONTEXTS_HXX_
#define _XMLOFF_FILLSTYLECONTEXTS_HXX_

#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif

#ifndef _XMLOFF_XMLSTYLE_HXX //autogen
#include <xmlstyle.hxx>
#endif

#ifndef _RTL_USTRING_
#include<rtl/ustring.hxx>
#endif

//////////////////////////////////////////////////////////////////////////////
// draw:gardient context

class XMLGradientStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLGradientStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLGradientStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:hatch context

class XMLHatchStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLHatchStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLHatchStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:fill-image context

class XMLBitmapStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > mxBase64Stream;

public:
    TYPEINFO();

    XMLBitmapStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLBitmapStyleContext();

    virtual SvXMLImportContext *CreateChildContext(
            sal_uInt16 nPrefix,
            const ::rtl::OUString& rLocalName,
            const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:transparency context

class XMLTransGradientStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLTransGradientStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLTransGradientStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:marker context

class XMLMarkerStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLMarkerStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLMarkerStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

//////////////////////////////////////////////////////////////////////////////
// draw:marker context

class XMLDashStyleContext: public SvXMLStyleContext
{
private:
    ::com::sun::star::uno::Any  maAny;
    rtl::OUString               maStrName;

public:
    TYPEINFO();

    XMLDashStyleContext( SvXMLImport& rImport,  sal_uInt16 nPrfx,  const rtl::OUString& rLName,
                           const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
    virtual ~XMLDashStyleContext();

    virtual void EndElement();

    virtual BOOL IsTransient() const;
};

#endif  // _XMLOFF_FILLSTYLECONTEXTS_HXX_
<|endoftext|>


<commit_before>//===-- Immediate.cpp - the swift immediate mode --------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This is the implementation of the swift interpreter, which takes a
// TranslationUnit and JITs it.
//
//===----------------------------------------------------------------------===//

#include "Immediate.h"
#include "Frontend.h"
#include "swift/Subsystems.h"
#include "swift/IRGen/Options.h"
#include "swift/Parse/Lexer.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Component.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Diagnostics.h"
#include "swift/AST/Module.h"
#include "swift/AST/Stmt.h"
#include "swift/Basic/DiagnosticConsumer.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Linker.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"

#include <cmath>
#include <histedit.h>
#include <dlfcn.h>

static void LoadSwiftRuntime() {
  // FIXME: Need error-checking.
  llvm::sys::Path LibPath =
      llvm::sys::Path::GetMainExecutable(0, (void*)&swift::RunImmediately);
  LibPath.eraseComponent();
  LibPath.eraseComponent();
  LibPath.appendComponent("lib");
  LibPath.appendComponent("libswift_abi.dylib");
  dlopen(LibPath.c_str(), 0);
}

void swift::RunImmediately(TranslationUnit *TU) {
  ASTContext &Context = TU->Ctx;
  irgen::Options Options;
  Options.OutputFilename = "";
  Options.Triple = llvm::sys::getDefaultTargetTriple();
  Options.OptLevel = 0;
  Options.OutputKind = irgen::OutputKind::Module;

  // IRGen the main module.
  llvm::LLVMContext LLVMContext;
  llvm::Module Module(TU->Name.str(), LLVMContext);
  performCaptureAnalysis(TU);
  performIRGeneration(Options, &Module, TU);

  if (Context.hadError())
    return;

  llvm::SmallPtrSet<TranslationUnit*, 8> ImportedModules;
  llvm::SmallVector<llvm::Function*, 4> InitFuncs;
  // IRGen the modules this module depends on.
  for (auto ModPair : TU->getImportedModules()) {
    if (isa<BuiltinModule>(ModPair.second))
      continue;

    TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);
    if (!ImportedModules.insert(SubTU))
      continue;

    // FIXME: Need to check whether this is actually safe in general.
    llvm::Module SubModule(SubTU->Name.str(), LLVMContext);
    performCaptureAnalysis(SubTU);
    performIRGeneration(Options, &SubModule, SubTU);

    if (Context.hadError())
      return;

    std::string ErrorMessage;
    if (llvm::Linker::LinkModules(&Module, &SubModule,
                                  llvm::Linker::DestroySource,
                                  &ErrorMessage)) {
      llvm::errs() << "Error linking swift modules\n";
      llvm::errs() << ErrorMessage << "\n";
      return;
    }

    // FIXME: This is an ugly hack; need to figure out how this should
    // actually work.
    SmallVector<char, 20> NameBuf;
    StringRef InitFnName = (SubTU->Name.str() + ".init").toStringRef(NameBuf);
    llvm::Function *InitFn = Module.getFunction(InitFnName);
    if (InitFn)
      InitFuncs.push_back(InitFn);
  }

  LoadSwiftRuntime();

  // Run the generated program.

  llvm::EngineBuilder builder(&Module);
  std::string ErrorMsg;
  builder.setErrorStr(&ErrorMsg);
  builder.setEngineKind(llvm::EngineKind::JIT);

  llvm::ExecutionEngine *EE = builder.create();
  for (auto InitFn : InitFuncs)
    EE->runFunctionAsMain(InitFn, std::vector<std::string>(), 0);

  llvm::Function *EntryFn = Module.getFunction("main");
  EE->runFunctionAsMain(EntryFn, std::vector<std::string>(), 0);
}

struct EditLineWrapper {
  EditLine *e;
  size_t PromptContinuationLevel;

  llvm::SmallString<80> PromptString;

  EditLineWrapper() {
    e = el_init("swift", stdin, stdout, stderr);
    PromptContinuationLevel = 0;
    el_set(e, EL_EDITOR, "emacs");
    el_set(e, EL_PROMPT, PromptFn);
    el_set(e, EL_CLIENTDATA, (void*)this);
  }

  static char *PromptFn(EditLine *e) {
    void* clientdata;
    el_get(e, EL_CLIENTDATA, &clientdata);
    return (char*)((EditLineWrapper*)clientdata)->getPrompt();
  }

  const char *getPrompt() {
    if (PromptContinuationLevel == 0)
      return "swift> ";

    PromptString = "swift| ";
    PromptString.append(2*PromptContinuationLevel, ' ');
    return PromptString.c_str();
  };

  ~EditLineWrapper() {
    el_end(e);
  }
  operator EditLine*() { return e; }
};

void swift::REPL(ASTContext &Context) {
  if (llvm::sys::Process::StandardInIsUserInput())
    printf("%s", "Welcome to swift.  Type 'help' for assistance.\n");

  // FIXME: We should do something a bit more elaborate than
  // "allocate a 1MB buffer and hope it's enough".
  llvm::MemoryBuffer *Buffer =
      llvm::MemoryBuffer::getNewMemBuffer(1 << 20, "<REPL Buffer>");

  Component *Comp = new (Context.Allocate<Component>(1)) Component();
  unsigned BufferID =
    Context.SourceMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
  Identifier ID = Context.getIdentifier("REPL");
  TranslationUnit *TU = new (Context) TranslationUnit(ID, Comp, Context,
                                                      /*IsMainModule=*/true,
                                                      /*IsReplModule=*/true);

  llvm::SmallPtrSet<TranslationUnit*, 8> ImportedModules;
  llvm::LLVMContext LLVMContext;
  llvm::Module Module("REPL", LLVMContext);
  std::string ErrorMessage;

  LoadSwiftRuntime();

  llvm::EngineBuilder builder(&Module);
  std::string ErrorMsg;
  builder.setErrorStr(&ErrorMsg);
  builder.setEngineKind(llvm::EngineKind::JIT);
  llvm::ExecutionEngine *EE = builder.create();

  irgen::Options Options;
  Options.OutputFilename = "";
  Options.Triple = llvm::sys::getDefaultTargetTriple();
  Options.OptLevel = 0;
  Options.OutputKind = irgen::OutputKind::Module;
  Options.IsREPL = true;

  EditLineWrapper e;

  char* CurBuffer = const_cast<char*>(Buffer->getBufferStart());
  unsigned CurBufferOffset = 0;
  unsigned CurBufferEndOffset = 0;

  unsigned CurTUElem = 0;
  unsigned BraceCount = 0;
  unsigned CurChunkLines = 0;

  while (1) {
    // Read one line.
    e.PromptContinuationLevel = BraceCount;
    int LineCount;
    const char* Line = el_gets(e, &LineCount);
    if (!Line)
      return;

    strcpy(CurBuffer, Line);
    CurBuffer += strlen(Line);
    CurBufferEndOffset += strlen(Line);
    ++CurChunkLines;

    // If we detect unbalanced braces, keep reading before we start parsing.
    Lexer L(Line, Context.SourceMgr, nullptr);
    Token Tok;
    do {
      L.lex(Tok);
      if (Tok.is(tok::l_brace))
        ++BraceCount;
      else if (Tok.is(tok::r_brace) && BraceCount > 0)
        --BraceCount;
    } while (!Tok.is(tok::eof));

    if (BraceCount)
      continue;

    // Parse the current line(s).
    bool ShouldRun =
        swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem,
                                           CurBufferOffset,
                                           CurBufferEndOffset);

    if (Context.hadError()) {
      Context.Diags.resetHadAnyError();
      while (TU->Decls.size() > CurTUElem)
        TU->Decls.pop_back();
      TU->clearUnresolvedIdentifierTypes();

      // FIXME: Handling of "import" declarations?  Is there any other
      // state which needs to be reset?

      if (CurChunkLines > 1)
        llvm::errs() << "(discarded " << CurChunkLines << " lines)\n";
      CurChunkLines = 0;
      continue;
    }

    // If we didn't see an expression, statement, or decl which might have
    // side-effects, keep reading.
    if (!ShouldRun)
      continue;

    // IRGen the current line(s).
    llvm::Module LineModule("REPLLine", LLVMContext);
    performCaptureAnalysis(TU, CurTUElem);
    performIRGeneration(Options, &LineModule, TU, CurTUElem);

    if (Context.hadError())
      return;

    CurTUElem = TU->Decls.size();
    CurChunkLines = 0;

    if (llvm::Linker::LinkModules(&Module, &LineModule,
                                  llvm::Linker::DestroySource,
                                  &ErrorMessage)) {
      llvm::errs() << "Error linking swift modules\n";
      llvm::errs() << ErrorMessage << "\n";
      return;
    }

    // IRGen the modules this module depends on.
    llvm::SmallVector<llvm::Function*, 4> InitFuncs;
    for (auto ModPair : TU->getImportedModules()) {
      if (isa<BuiltinModule>(ModPair.second))
        continue;

      TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);
      if (!ImportedModules.insert(SubTU))
        continue;

      // FIXME: Need to check whether this is actually safe in general.
      llvm::Module SubModule(SubTU->Name.str(), LLVMContext);
      performCaptureAnalysis(SubTU);
      performIRGeneration(Options, &SubModule, SubTU);

      if (Context.hadError())
        return;

      if (llvm::Linker::LinkModules(&Module, &SubModule,
                                    llvm::Linker::DestroySource,
                                    &ErrorMessage)) {
        llvm::errs() << "Error linking swift modules\n";
        llvm::errs() << ErrorMessage << "\n";
        return;
      }

      // FIXME: This is an ugly hack; need to figure out how this should
      // actually work.
      SmallVector<char, 20> NameBuf;
      StringRef InitFnName = (SubTU->Name.str() + ".init").toStringRef(NameBuf);
      llvm::Function *InitFn = Module.getFunction(InitFnName);
      if (InitFn)
        InitFuncs.push_back(InitFn);
    }

    for (auto InitFn : InitFuncs)
      EE->runFunctionAsMain(InitFn, std::vector<std::string>(), 0);

    // FIXME: The way we do this is really ugly... we should be able to
    // improve this.
    llvm::Function *EntryFn = Module.getFunction("main");
    EE->runFunctionAsMain(EntryFn, std::vector<std::string>(), 0);
    EE->freeMachineCodeForFunction(EntryFn);
    EntryFn->eraseFromParent();
  }
}

// FIXME: We shouldn't be writing implemenetations for functions in the swift
// module in C, and this isn't really an ideal place to put those
// implementations.
extern "C" void _TSs5printFT3valNSs5Int64_T_(int64_t l) {
  printf("%lld", l);
}

extern "C" void _TSs5printFT3valNSs6Double_T_(double l) {
  char Buffer[256];
  sprintf(Buffer, "%g", l);
  if (llvm::StringRef((char*)Buffer).find_first_of(".e") == llvm::StringRef::npos)
    strcat(Buffer, ".0");
  printf("%s", Buffer);
}

extern "C" void _TSs9printCharFT9characterNSs5Int32_T_(int32_t l) {
  printf("%c", (char)l);
}

// String implementation.

// func [infix_left=190] + (lhs : String,
//                          rhs : String) -> String
extern "C" char* _TSsop1pFT3lhsNSs6String3rhsS__S_(char* lhs, char* rhs) {
   size_t ls = strlen(lhs);
   size_t rs = strlen(rhs);
   char* s = (char*)malloc(ls+rs+1);
   memcpy(s, lhs, ls);
   strcpy(s+ls, rhs);
   return s;
}

// static func String(v : Int128) -> String
extern "C" char *_TNSs6String6StringFT1vNSs6Int128_S_(__int128_t X) {
  char TmpBuffer[128];
  char *P = TmpBuffer+128;

  *--P = 0; // Null terminate buffer.

  bool WasNeg = X < 0;
  __uint128_t Y = WasNeg ? -X : X;

  if (Y == 0) *--P = 0;  // Special case.

  while (Y) {
    *--P = '0' + char(Y % 10);
    Y /= 10;
  }

  if (WasNeg) *--P = '-';
  return strdup(P);
}

// static func String(v : Double) -> String
extern "C" char *_TNSs6String6StringFT1vNSs6Double_S_(double X) {
  // TODO: optimize with snprintf etc if anyone cares.
  llvm::SmallString<128> Result;
  {
    llvm::raw_svector_ostream Str(Result);
    Str << X;
  }
  return strdup(Result.c_str());
}

extern "C" bool _TNSs4Bool13getLogicValuefRS_FT_i1(bool* b) {
  return *b;
}

extern "C" void _TSs4exitFT8exitCodeNSs5Int64_T_(int64_t l) {
  exit(l);
}

extern "C" void _TSs5abortFT_T_() {
  abort();
}

extern "C" double _TSs4sqrtFT1aNSs6Double_S_(double X) { return sqrt(X); }
extern "C" float _TSs4sqrtFT1aNSs5Float_S_(float X) {
  return sqrtf(X);
}

extern "C" double _TSs3sinFT1aNSs6Double_S_(double X) { return sin(X); }
extern "C" float _TSs3sinFT1aNSs5Float_S_(float X) {
  return sinf(X);
}

extern "C" double _TSs3cosFT1aNSs6Double_S_(double X) { return cos(X); }
extern "C" float _TSs3cosFT1aNSs5Float_S_(float X) {
  return cosf(X);
}

extern "C" double _TSs5atan2FT1yNSs6Double1xS__S_(double Y, double X) {
  return atan2(Y, X);
}
extern "C" float _TSs5atan2FT1yNSs5Float1xS__S_(float Y, float X) {
  return atan2f(Y, X);
}

<commit_msg>Add simple interpreter escapes.  Use ':' since it's reserved by the swift grammar.  <rdar://problem/11296710>.<commit_after>//===-- Immediate.cpp - the swift immediate mode --------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This is the implementation of the swift interpreter, which takes a
// TranslationUnit and JITs it.
//
//===----------------------------------------------------------------------===//

#include "Immediate.h"
#include "Frontend.h"
#include "swift/Subsystems.h"
#include "swift/IRGen/Options.h"
#include "swift/Parse/Lexer.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Component.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Diagnostics.h"
#include "swift/AST/Module.h"
#include "swift/AST/Stmt.h"
#include "swift/Basic/DiagnosticConsumer.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Linker.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"

#include <cmath>
#include <histedit.h>
#include <dlfcn.h>

static void LoadSwiftRuntime() {
  // FIXME: Need error-checking.
  llvm::sys::Path LibPath =
      llvm::sys::Path::GetMainExecutable(0, (void*)&swift::RunImmediately);
  LibPath.eraseComponent();
  LibPath.eraseComponent();
  LibPath.appendComponent("lib");
  LibPath.appendComponent("libswift_abi.dylib");
  dlopen(LibPath.c_str(), 0);
}

void swift::RunImmediately(TranslationUnit *TU) {
  ASTContext &Context = TU->Ctx;
  irgen::Options Options;
  Options.OutputFilename = "";
  Options.Triple = llvm::sys::getDefaultTargetTriple();
  Options.OptLevel = 0;
  Options.OutputKind = irgen::OutputKind::Module;

  // IRGen the main module.
  llvm::LLVMContext LLVMContext;
  llvm::Module Module(TU->Name.str(), LLVMContext);
  performCaptureAnalysis(TU);
  performIRGeneration(Options, &Module, TU);

  if (Context.hadError())
    return;

  llvm::SmallPtrSet<TranslationUnit*, 8> ImportedModules;
  llvm::SmallVector<llvm::Function*, 4> InitFuncs;
  // IRGen the modules this module depends on.
  for (auto ModPair : TU->getImportedModules()) {
    if (isa<BuiltinModule>(ModPair.second))
      continue;

    TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);
    if (!ImportedModules.insert(SubTU))
      continue;

    // FIXME: Need to check whether this is actually safe in general.
    llvm::Module SubModule(SubTU->Name.str(), LLVMContext);
    performCaptureAnalysis(SubTU);
    performIRGeneration(Options, &SubModule, SubTU);

    if (Context.hadError())
      return;

    std::string ErrorMessage;
    if (llvm::Linker::LinkModules(&Module, &SubModule,
                                  llvm::Linker::DestroySource,
                                  &ErrorMessage)) {
      llvm::errs() << "Error linking swift modules\n";
      llvm::errs() << ErrorMessage << "\n";
      return;
    }

    // FIXME: This is an ugly hack; need to figure out how this should
    // actually work.
    SmallVector<char, 20> NameBuf;
    StringRef InitFnName = (SubTU->Name.str() + ".init").toStringRef(NameBuf);
    llvm::Function *InitFn = Module.getFunction(InitFnName);
    if (InitFn)
      InitFuncs.push_back(InitFn);
  }

  LoadSwiftRuntime();

  // Run the generated program.

  llvm::EngineBuilder builder(&Module);
  std::string ErrorMsg;
  builder.setErrorStr(&ErrorMsg);
  builder.setEngineKind(llvm::EngineKind::JIT);

  llvm::ExecutionEngine *EE = builder.create();
  for (auto InitFn : InitFuncs)
    EE->runFunctionAsMain(InitFn, std::vector<std::string>(), 0);

  llvm::Function *EntryFn = Module.getFunction("main");
  EE->runFunctionAsMain(EntryFn, std::vector<std::string>(), 0);
}

struct EditLineWrapper {
  EditLine *e;
  size_t PromptContinuationLevel;

  llvm::SmallString<80> PromptString;

  EditLineWrapper() {
    e = el_init("swift", stdin, stdout, stderr);
    PromptContinuationLevel = 0;
    el_set(e, EL_EDITOR, "emacs");
    el_set(e, EL_PROMPT, PromptFn);
    el_set(e, EL_CLIENTDATA, (void*)this);
  }

  static char *PromptFn(EditLine *e) {
    void* clientdata;
    el_get(e, EL_CLIENTDATA, &clientdata);
    return (char*)((EditLineWrapper*)clientdata)->getPrompt();
  }

  const char *getPrompt() {
    if (PromptContinuationLevel == 0)
      return "swift> ";

    PromptString = "swift| ";
    PromptString.append(2*PromptContinuationLevel, ' ');
    return PromptString.c_str();
  };

  ~EditLineWrapper() {
    el_end(e);
  }
  operator EditLine*() { return e; }
};

void swift::REPL(ASTContext &Context) {
  if (llvm::sys::Process::StandardInIsUserInput())
    printf("%s", "Welcome to swift.  Type ':help' for assistance.\n");

  // FIXME: We should do something a bit more elaborate than
  // "allocate a 1MB buffer and hope it's enough".
  llvm::MemoryBuffer *Buffer =
      llvm::MemoryBuffer::getNewMemBuffer(1 << 20, "<REPL Buffer>");

  Component *Comp = new (Context.Allocate<Component>(1)) Component();
  unsigned BufferID =
    Context.SourceMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
  Identifier ID = Context.getIdentifier("REPL");
  TranslationUnit *TU = new (Context) TranslationUnit(ID, Comp, Context,
                                                      /*IsMainModule=*/true,
                                                      /*IsReplModule=*/true);

  llvm::SmallPtrSet<TranslationUnit*, 8> ImportedModules;
  llvm::LLVMContext LLVMContext;
  llvm::Module Module("REPL", LLVMContext);
  std::string ErrorMessage;

  LoadSwiftRuntime();

  llvm::EngineBuilder builder(&Module);
  std::string ErrorMsg;
  builder.setErrorStr(&ErrorMsg);
  builder.setEngineKind(llvm::EngineKind::JIT);
  llvm::ExecutionEngine *EE = builder.create();

  irgen::Options Options;
  Options.OutputFilename = "";
  Options.Triple = llvm::sys::getDefaultTargetTriple();
  Options.OptLevel = 0;
  Options.OutputKind = irgen::OutputKind::Module;
  Options.IsREPL = true;

  EditLineWrapper e;

  char* CurBuffer = const_cast<char*>(Buffer->getBufferStart());
  unsigned CurBufferOffset = 0;
  unsigned CurBufferEndOffset = 0;

  unsigned CurTUElem = 0;
  unsigned BraceCount = 0;
  unsigned CurChunkLines = 0;

  while (1) {
    // Read one line.
    e.PromptContinuationLevel = BraceCount;
    int LineCount;
    const char* Line = el_gets(e, &LineCount);
    if (!Line)
      return;

    strcpy(CurBuffer, Line);
    CurBuffer += strlen(Line);
    CurBufferEndOffset += strlen(Line);
    ++CurChunkLines;

    // If we detect unbalanced braces, keep reading before we start parsing.
    Lexer L(Line, Context.SourceMgr, nullptr);
    Token Tok;
    L.lex(Tok);
    if (CurChunkLines == 1 && !BraceCount && Tok.is(tok::colon)) {
      if (L.peekNextToken().getText() == "help") {
        printf("%s", "I'm not helpful yet, but use :quit to exit\n");
      } else if (L.peekNextToken().getText() == "quit" ||
                 L.peekNextToken().getText() == "exit") {
        return;
      } else {
        printf("%s", "Unknown interpreter escape; try :help\n");
      }
      CurBufferOffset = CurBufferEndOffset;
      CurChunkLines = 0;
      continue;
    }
    do {
      if (Tok.is(tok::l_brace))
        ++BraceCount;
      else if (Tok.is(tok::r_brace) && BraceCount > 0)
        --BraceCount;
      else if (Tok.is(tok::eof))
        break;

      L.lex(Tok);
    } while (1);

    if (BraceCount)
      continue;

    // Parse the current line(s).
    bool ShouldRun =
        swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem,
                                           CurBufferOffset,
                                           CurBufferEndOffset);

    if (Context.hadError()) {
      Context.Diags.resetHadAnyError();
      while (TU->Decls.size() > CurTUElem)
        TU->Decls.pop_back();
      TU->clearUnresolvedIdentifierTypes();

      // FIXME: Handling of "import" declarations?  Is there any other
      // state which needs to be reset?

      if (CurChunkLines > 1)
        llvm::errs() << "(discarded " << CurChunkLines << " lines)\n";
      CurChunkLines = 0;
      continue;
    }

    // If we didn't see an expression, statement, or decl which might have
    // side-effects, keep reading.
    if (!ShouldRun)
      continue;

    // IRGen the current line(s).
    llvm::Module LineModule("REPLLine", LLVMContext);
    performCaptureAnalysis(TU, CurTUElem);
    performIRGeneration(Options, &LineModule, TU, CurTUElem);

    if (Context.hadError())
      return;

    CurTUElem = TU->Decls.size();
    CurChunkLines = 0;

    if (llvm::Linker::LinkModules(&Module, &LineModule,
                                  llvm::Linker::DestroySource,
                                  &ErrorMessage)) {
      llvm::errs() << "Error linking swift modules\n";
      llvm::errs() << ErrorMessage << "\n";
      return;
    }

    // IRGen the modules this module depends on.
    llvm::SmallVector<llvm::Function*, 4> InitFuncs;
    for (auto ModPair : TU->getImportedModules()) {
      if (isa<BuiltinModule>(ModPair.second))
        continue;

      TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);
      if (!ImportedModules.insert(SubTU))
        continue;

      // FIXME: Need to check whether this is actually safe in general.
      llvm::Module SubModule(SubTU->Name.str(), LLVMContext);
      performCaptureAnalysis(SubTU);
      performIRGeneration(Options, &SubModule, SubTU);

      if (Context.hadError())
        return;

      if (llvm::Linker::LinkModules(&Module, &SubModule,
                                    llvm::Linker::DestroySource,
                                    &ErrorMessage)) {
        llvm::errs() << "Error linking swift modules\n";
        llvm::errs() << ErrorMessage << "\n";
        return;
      }

      // FIXME: This is an ugly hack; need to figure out how this should
      // actually work.
      SmallVector<char, 20> NameBuf;
      StringRef InitFnName = (SubTU->Name.str() + ".init").toStringRef(NameBuf);
      llvm::Function *InitFn = Module.getFunction(InitFnName);
      if (InitFn)
        InitFuncs.push_back(InitFn);
    }

    for (auto InitFn : InitFuncs)
      EE->runFunctionAsMain(InitFn, std::vector<std::string>(), 0);

    // FIXME: The way we do this is really ugly... we should be able to
    // improve this.
    llvm::Function *EntryFn = Module.getFunction("main");
    EE->runFunctionAsMain(EntryFn, std::vector<std::string>(), 0);
    EE->freeMachineCodeForFunction(EntryFn);
    EntryFn->eraseFromParent();
  }
}

// FIXME: We shouldn't be writing implemenetations for functions in the swift
// module in C, and this isn't really an ideal place to put those
// implementations.
extern "C" void _TSs5printFT3valNSs5Int64_T_(int64_t l) {
  printf("%lld", l);
}

extern "C" void _TSs5printFT3valNSs6Double_T_(double l) {
  char Buffer[256];
  sprintf(Buffer, "%g", l);
  if (llvm::StringRef((char*)Buffer).find_first_of(".e") == llvm::StringRef::npos)
    strcat(Buffer, ".0");
  printf("%s", Buffer);
}

extern "C" void _TSs9printCharFT9characterNSs5Int32_T_(int32_t l) {
  printf("%c", (char)l);
}

// String implementation.

// func [infix_left=190] + (lhs : String,
//                          rhs : String) -> String
extern "C" char* _TSsop1pFT3lhsNSs6String3rhsS__S_(char* lhs, char* rhs) {
   size_t ls = strlen(lhs);
   size_t rs = strlen(rhs);
   char* s = (char*)malloc(ls+rs+1);
   memcpy(s, lhs, ls);
   strcpy(s+ls, rhs);
   return s;
}

// static func String(v : Int128) -> String
extern "C" char *_TNSs6String6StringFT1vNSs6Int128_S_(__int128_t X) {
  char TmpBuffer[128];
  char *P = TmpBuffer+128;

  *--P = 0; // Null terminate buffer.

  bool WasNeg = X < 0;
  __uint128_t Y = WasNeg ? -X : X;

  if (Y == 0) *--P = 0;  // Special case.

  while (Y) {
    *--P = '0' + char(Y % 10);
    Y /= 10;
  }

  if (WasNeg) *--P = '-';
  return strdup(P);
}

// static func String(v : Double) -> String
extern "C" char *_TNSs6String6StringFT1vNSs6Double_S_(double X) {
  // TODO: optimize with snprintf etc if anyone cares.
  llvm::SmallString<128> Result;
  {
    llvm::raw_svector_ostream Str(Result);
    Str << X;
  }
  return strdup(Result.c_str());
}

extern "C" bool _TNSs4Bool13getLogicValuefRS_FT_i1(bool* b) {
  return *b;
}

extern "C" void _TSs4exitFT8exitCodeNSs5Int64_T_(int64_t l) {
  exit(l);
}

extern "C" void _TSs5abortFT_T_() {
  abort();
}

extern "C" double _TSs4sqrtFT1aNSs6Double_S_(double X) { return sqrt(X); }
extern "C" float _TSs4sqrtFT1aNSs5Float_S_(float X) {
  return sqrtf(X);
}

extern "C" double _TSs3sinFT1aNSs6Double_S_(double X) { return sin(X); }
extern "C" float _TSs3sinFT1aNSs5Float_S_(float X) {
  return sinf(X);
}

extern "C" double _TSs3cosFT1aNSs6Double_S_(double X) { return cos(X); }
extern "C" float _TSs3cosFT1aNSs5Float_S_(float X) {
  return cosf(X);
}

extern "C" double _TSs5atan2FT1yNSs6Double1xS__S_(double Y, double X) {
  return atan2(Y, X);
}
extern "C" float _TSs5atan2FT1yNSs5Float1xS__S_(float Y, float X) {
  return atan2f(Y, X);
}

<|endoftext|>


<commit_before>//
// Copyright (c) articy Software GmbH & Co. KG. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#include "Slate/AssetPicker/SArticyObjectToolTip.h"
#include "ArticyFlowClasses.h"
#include "Interfaces/ArticyObjectWithDisplayName.h"
#include "Interfaces/ArticyObjectWithText.h"
#include <Widgets/SBoxPanel.h>
#include <Widgets/Text/STextBlock.h>
#include <EditorStyleSet.h>
#include <Widgets/Layout/SBorder.h>
#include <Widgets/SToolTip.h>
#include <Internationalization/Text.h>
#include "Slate/UserInterfaceHelperFunctions.h"
#include "Interfaces/ArticyObjectWithSpeaker.h"
#include "Widgets/Layout/SScaleBox.h"

#define LOCTEXT_NAMESPACE "ArticyObjectToolTip"

void SArticyObjectToolTip::Construct(const FArguments& InArgs)
{
	ArticyIdAttribute = InArgs._ObjectToDisplay;

	TooltipBrush.ImageSize = FVector2D(64.f, 64.f);

	SToolTip::Construct(
		SToolTip::FArguments()
		.TextMargin(1.f)
		.BorderImage(FEditorStyle::Get().GetBrush("ContentBrowser.TileViewTooltip.ToolTipBorder"))
		// Text makes tooltip show, probably because it doesn't initialize otherwise
		.Text(FText::FromString("TEST"))
		);

}

void SArticyObjectToolTip::OnOpening()
{
	if(CachedArticyObject.IsValid())
	{
		SetContentWidget(CreateToolTipContent());
	}
	else
	{
		SetContentWidget(CreateEmptyContent());
	}

}

void SArticyObjectToolTip::OnClosed()
{
	SetContentWidget(SNullWidget::NullWidget);
}

void SArticyObjectToolTip::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	if(CachedArticyId != ArticyIdAttribute.Get())
	{
		UpdateWidget();
	}
}

TSharedRef<SWidget> SArticyObjectToolTip::CreateToolTipContent()
{
	check(CachedArticyObject.IsValid());

	// use the preview image if available
	const bool bHasPreviewImage = UserInterfaceHelperFunctions::RetrievePreviewImage(CachedArticyObject.Get(), TooltipBrush);

	// if there is no preview image, use the preview image of the speaker, if available
	if (!bHasPreviewImage)
	{
		const bool bHasSpeakerPreviewImage = UserInterfaceHelperFunctions::RetrieveSpeakerPreviewImage(CachedArticyObject.Get(), TooltipBrush);

		// if there is no speaker preview image, use the type image instead
		if (!bHasSpeakerPreviewImage)
		{
			TooltipBrush = *UserInterfaceHelperFunctions::GetArticyTypeImage(CachedArticyObject.Get(), UserInterfaceHelperFunctions::Large);
		}
	}

	const FString AssetName = CachedArticyObject.Get()->GetName();
	const UClass* ClassOfObject = CachedArticyObject.Get()->UObject::GetClass();

	// The tooltip contains the name, class, path, and asset registry tags
	// Use asset name by default, overwrite with display name where it makes sense
	FText NameText = FText::FromString(AssetName);
	const FText ClassText = FText::Format(LOCTEXT("ClassName", "({0})"), FText::FromString(ClassOfObject->GetName()));

	// Create a box to hold every line of info in the body of the tooltip
	TSharedRef<SVerticalBox> InfoBox = SNew(SVerticalBox);

	// overwrite the asset name with the display name
	bool bUsingDisplayName = false;
	IArticyObjectWithDisplayName* ArticyObjectWithDisplayName = Cast<IArticyObjectWithDisplayName>(CachedArticyObject);
	if (ArticyObjectWithDisplayName)
	{
		const FText DisplayName = ArticyObjectWithDisplayName->GetDisplayName();
		if(!DisplayName.IsEmpty())
		{
			NameText = DisplayName;
			bUsingDisplayName = true;
		}
	}

	IArticyObjectWithSpeaker* ArticyObjectWithSpeaker = Cast<IArticyObjectWithSpeaker>(CachedArticyObject);
	if(ArticyObjectWithSpeaker)
	{
		const UArticyObject* Speaker = UArticyObject::FindAsset(ArticyObjectWithSpeaker->GetSpeakerId());
		// Speaker can be nullptr in case a speaker that does not exist as an entity was specified, i.e. in the scriptwriting documents
		if (Speaker)
		{
			const IArticyObjectWithDisplayName* DisplayNameOfSpeaker = Cast<IArticyObjectWithDisplayName>(Speaker);
			const FText DisplayName = DisplayNameOfSpeaker->GetDisplayName();
			AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipSpeaker", "Speaker"), DisplayName, true);
		}
		else
		{
			UE_LOG(LogArticyImporter, Error, TEXT("Articy tooltip: Speaker object does not exist"))
		}

	}

	// add the text to the tooltip body if possible
	IArticyObjectWithText* ArticyObjectWithText = Cast<IArticyObjectWithText>(CachedArticyObject);
	if (ArticyObjectWithText)
	{
		const FText& Text = ArticyObjectWithText->GetText();
		if (Text.IsEmpty())
		{
			// if there is empty text, add no text at all - maybe "..." or "Empty"?
		}
		else
		{
			AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipText", "Text"), FText::FromString(FString("\"").Append(Text.ToString()).Append("\"")), true);
		}
	}

	// if we overwrote the asset name with the display name, attach the asset name in the tooltip body
	if (bUsingDisplayName)
	{
		AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipAssetName", "Asset Name"), FText::FromString(AssetName), false);
	}

	// add class name
	AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipClass", "Class"), ClassText, false);

	TSharedRef<SVerticalBox> OverallTooltipVBox = SNew(SVerticalBox);

	// Top section (asset name, type, is checked out)
	OverallTooltipVBox->AddSlot()
		.AutoHeight()
		.Padding(0, 0, 0, 4)
		[
			SNew(SBorder)
			.Padding(6)
			.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder"))
			[
				SNew(SVerticalBox)
				+ SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(SHorizontalBox)
					+ SHorizontalBox::Slot()
					.VAlign(VAlign_Center)
					.Padding(0, 0, 4, 0)
					[
						SNew(STextBlock)
						.Text(NameText)
						.Font(FEditorStyle::GetFontStyle("ContentBrowser.TileViewTooltip.NameFont"))
						.AutoWrapText(true)
					]
				]
			]
		];

	// Bottom section (additional information)
	OverallTooltipVBox->AddSlot()
	.AutoHeight()
	[
		SNew(SBorder)
		.Padding(6)
		.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder"))
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				InfoBox
			]
			+ SHorizontalBox::Slot()
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Top)
			.AutoWidth()
			[
				SNew(SBox)
				.Padding(FMargin(10, 2, 2, 2))
				[
					SNew(SImage)
					.Image(this, &SArticyObjectToolTip::GetTooltipImage)
				]
			]
		]
	];

	return SNew(SBorder)
	.Padding(6)
	.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.NonContentBorder"))
	[
		SNew(SBox)
		.MaxDesiredWidth(500.f)
		[
			OverallTooltipVBox
		]
	];
}

TSharedRef<SWidget> SArticyObjectToolTip::CreateEmptyContent()
{
	check(!CachedArticyObject.IsValid());

	// Create an empty box and return it to effectively clear the tooltip.
	// SNullWidget::NullWidget does not work because it is filtered out byy the SetContent function
	TSharedRef<SVerticalBox> InfoBox = SNew(SVerticalBox);
	return InfoBox;
}

void SArticyObjectToolTip::AddToToolTipInfoBox(const TSharedRef<SVerticalBox>& InfoBox, const FText& Key, const FText& Value, bool bImportant) const
{
	FWidgetStyle ImportantStyle;
	ImportantStyle.SetForegroundColor(FLinearColor(1, 0.5, 0, 1));

	InfoBox->AddSlot()
		.AutoHeight()
		.Padding(0, 1)
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(0, 0, 4, 0)
			[
				SNew(STextBlock).Text(FText::Format(LOCTEXT("AssetViewTooltipFormat", "{0}:"), Key))
				.ColorAndOpacity(bImportant ? ImportantStyle.GetSubduedForegroundColor() : FSlateColor::UseSubduedForeground())
			]

			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				// highlighting text reference: AssetViewWidgets.cpp 1118
				SNew(STextBlock).Text(Value)
				.WrapTextAt(400)
				.ColorAndOpacity(bImportant ? ImportantStyle.GetForegroundColor() : FSlateColor::UseSubduedForeground())
				.WrappingPolicy(ETextWrappingPolicy::AllowPerCharacterWrapping)
			]
		];
}

void SArticyObjectToolTip::UpdateWidget()
{
	CachedArticyId = ArticyIdAttribute.Get();
	CachedArticyObject = UArticyObject::FindAsset(CachedArticyId);

	if(CachedArticyObject.IsValid())
	{
		SetContentWidget(CreateToolTipContent());
	}
	else
	{
		SetContentWidget(CreateEmptyContent());
	}
}

const FSlateBrush* SArticyObjectToolTip::GetTooltipImage() const
{
	return &TooltipBrush;
}

#undef LOCTEXT_NAMESPACE
<commit_msg>Added target line to tooltips<commit_after>//
// Copyright (c) articy Software GmbH & Co. KG. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#include "Slate/AssetPicker/SArticyObjectToolTip.h"
#include "ArticyFlowClasses.h"
#include "Interfaces/ArticyObjectWithDisplayName.h"
#include "Interfaces/ArticyObjectWithText.h"
#include <Widgets/SBoxPanel.h>
#include <Widgets/Text/STextBlock.h>
#include <EditorStyleSet.h>
#include <Widgets/Layout/SBorder.h>
#include <Widgets/SToolTip.h>
#include <Internationalization/Text.h>
#include "Slate/UserInterfaceHelperFunctions.h"
#include "Interfaces/ArticyObjectWithSpeaker.h"
#include "Widgets/Layout/SScaleBox.h"

#define LOCTEXT_NAMESPACE "ArticyObjectToolTip"

void SArticyObjectToolTip::Construct(const FArguments& InArgs)
{
	ArticyIdAttribute = InArgs._ObjectToDisplay;

	TooltipBrush.ImageSize = FVector2D(64.f, 64.f);

	SToolTip::Construct(
		SToolTip::FArguments()
		.TextMargin(1.f)
		.BorderImage(FEditorStyle::Get().GetBrush("ContentBrowser.TileViewTooltip.ToolTipBorder"))
		// Text makes tooltip show, probably because it doesn't initialize otherwise
		.Text(FText::FromString("TEST"))
		);

}

void SArticyObjectToolTip::OnOpening()
{
	if(CachedArticyObject.IsValid())
	{
		SetContentWidget(CreateToolTipContent());
	}
	else
	{
		SetContentWidget(CreateEmptyContent());
	}

}

void SArticyObjectToolTip::OnClosed()
{
	SetContentWidget(SNullWidget::NullWidget);
}

void SArticyObjectToolTip::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	if(CachedArticyId != ArticyIdAttribute.Get())
	{
		UpdateWidget();
	}
}

TSharedRef<SWidget> SArticyObjectToolTip::CreateToolTipContent()
{
	check(CachedArticyObject.IsValid());

	// use the preview image if available
	const bool bHasPreviewImage = UserInterfaceHelperFunctions::RetrievePreviewImage(CachedArticyObject.Get(), TooltipBrush);

	// if there is no preview image, use the preview image of the speaker, if available
	if (!bHasPreviewImage)
	{
		const bool bHasSpeakerPreviewImage = UserInterfaceHelperFunctions::RetrieveSpeakerPreviewImage(CachedArticyObject.Get(), TooltipBrush);

		// if there is no speaker preview image, use the type image instead
		if (!bHasSpeakerPreviewImage)
		{
			TooltipBrush = *UserInterfaceHelperFunctions::GetArticyTypeImage(CachedArticyObject.Get(), UserInterfaceHelperFunctions::Large);
		}
	}

	const FString AssetName = CachedArticyObject.Get()->GetName();
	const UClass* ClassOfObject = CachedArticyObject.Get()->UObject::GetClass();

	// The tooltip contains the name, class, path, and asset registry tags
	// Use asset name by default, overwrite with display name where it makes sense
	FText NameText = FText::FromString(AssetName);
	const FText ClassText = FText::Format(LOCTEXT("ClassName", "({0})"), FText::FromString(ClassOfObject->GetName()));

	// Create a box to hold every line of info in the body of the tooltip
	TSharedRef<SVerticalBox> InfoBox = SNew(SVerticalBox);

	// overwrite the asset name with the display name
	bool bUsingDisplayName = false;
	IArticyObjectWithDisplayName* ArticyObjectWithDisplayName = Cast<IArticyObjectWithDisplayName>(CachedArticyObject);
	if (ArticyObjectWithDisplayName)
	{
		const FText DisplayName = ArticyObjectWithDisplayName->GetDisplayName();
		if(!DisplayName.IsEmpty())
		{
			NameText = DisplayName;
			bUsingDisplayName = true;
		}
	}

	IArticyObjectWithSpeaker* ArticyObjectWithSpeaker = Cast<IArticyObjectWithSpeaker>(CachedArticyObject);
	if(ArticyObjectWithSpeaker)
	{
		const UArticyObject* Speaker = UArticyObject::FindAsset(ArticyObjectWithSpeaker->GetSpeakerId());
		// Speaker can be nullptr in case a speaker that does not exist as an entity was specified, i.e. in the scriptwriting documents
		if (Speaker)
		{
			const IArticyObjectWithDisplayName* DisplayNameOfSpeaker = Cast<IArticyObjectWithDisplayName>(Speaker);
			const FText DisplayName = DisplayNameOfSpeaker->GetDisplayName();
			AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipSpeaker", "Speaker"), DisplayName, true);
		}
		else
		{
			UE_LOG(LogArticyImporter, Error, TEXT("Articy tooltip: Speaker object does not exist"))
		}

	}

	// add the text to the tooltip body if possible
	IArticyObjectWithText* ArticyObjectWithText = Cast<IArticyObjectWithText>(CachedArticyObject);
	if (ArticyObjectWithText)
	{
		const FText& Text = ArticyObjectWithText->GetText();
		if (Text.IsEmpty())
		{
			// if there is empty text, add no text at all - maybe "..." or "Empty"?
		}
		else
		{
			AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipText", "Text"), FText::FromString(FString("\"").Append(Text.ToString()).Append("\"")), true);
		}
	}

	// if we overwrote the asset name with the display name, attach the asset name in the tooltip body
	if (bUsingDisplayName)
	{
		AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipAssetName", "Asset Name"), FText::FromString(AssetName), false);
	}

	// if our object has a target, add the display name of the target to the tooltip
	const FArticyId* TargetID = UserInterfaceHelperFunctions::GetTargetID(CachedArticyObject.Get());
	if(TargetID)
	{
		UArticyObject* TargetObject = UArticyObject::FindAsset(*TargetID);
		if(TargetObject)
		{
			AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipTarget", "Target"), FText::FromString(UserInterfaceHelperFunctions::GetDisplayName(TargetObject)), false);
		}
	}

	// add class name
	AddToToolTipInfoBox(InfoBox, LOCTEXT("ArticyObjectToolTipClass", "Class"), ClassText, false);

	TSharedRef<SVerticalBox> OverallTooltipVBox = SNew(SVerticalBox);

	// Top section (asset name, type, is checked out)
	OverallTooltipVBox->AddSlot()
		.AutoHeight()
		.Padding(0, 0, 0, 4)
		[
			SNew(SBorder)
			.Padding(6)
			.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder"))
			[
				SNew(SVerticalBox)
				+ SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(SHorizontalBox)
					+ SHorizontalBox::Slot()
					.VAlign(VAlign_Center)
					.Padding(0, 0, 4, 0)
					[
						SNew(STextBlock)
						.Text(NameText)
						.Font(FEditorStyle::GetFontStyle("ContentBrowser.TileViewTooltip.NameFont"))
						.AutoWrapText(true)
					]
				]
			]
		];

	// Bottom section (additional information)
	OverallTooltipVBox->AddSlot()
	.AutoHeight()
	[
		SNew(SBorder)
		.Padding(6)
		.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder"))
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				InfoBox
			]
			+ SHorizontalBox::Slot()
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Top)
			.AutoWidth()
			[
				SNew(SBox)
				.Padding(FMargin(10, 2, 2, 2))
				[
					SNew(SImage)
					.Image(this, &SArticyObjectToolTip::GetTooltipImage)
				]
			]
		]
	];

	return SNew(SBorder)
	.Padding(6)
	.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.NonContentBorder"))
	[
		SNew(SBox)
		.MaxDesiredWidth(500.f)
		[
			OverallTooltipVBox
		]
	];
}

TSharedRef<SWidget> SArticyObjectToolTip::CreateEmptyContent()
{
	check(!CachedArticyObject.IsValid());

	// Create an empty box and return it to effectively clear the tooltip.
	// SNullWidget::NullWidget does not work because it is filtered out byy the SetContent function
	TSharedRef<SVerticalBox> InfoBox = SNew(SVerticalBox);
	return InfoBox;
}

void SArticyObjectToolTip::AddToToolTipInfoBox(const TSharedRef<SVerticalBox>& InfoBox, const FText& Key, const FText& Value, bool bImportant) const
{
	FWidgetStyle ImportantStyle;
	ImportantStyle.SetForegroundColor(FLinearColor(1, 0.5, 0, 1));

	InfoBox->AddSlot()
		.AutoHeight()
		.Padding(0, 1)
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(0, 0, 4, 0)
			[
				SNew(STextBlock).Text(FText::Format(LOCTEXT("AssetViewTooltipFormat", "{0}:"), Key))
				.ColorAndOpacity(bImportant ? ImportantStyle.GetSubduedForegroundColor() : FSlateColor::UseSubduedForeground())
			]

			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				// highlighting text reference: AssetViewWidgets.cpp 1118
				SNew(STextBlock).Text(Value)
				.WrapTextAt(400)
				.ColorAndOpacity(bImportant ? ImportantStyle.GetForegroundColor() : FSlateColor::UseSubduedForeground())
				.WrappingPolicy(ETextWrappingPolicy::AllowPerCharacterWrapping)
			]
		];
}

void SArticyObjectToolTip::UpdateWidget()
{
	CachedArticyId = ArticyIdAttribute.Get();
	CachedArticyObject = UArticyObject::FindAsset(CachedArticyId);

	if(CachedArticyObject.IsValid())
	{
		SetContentWidget(CreateToolTipContent());
	}
	else
	{
		SetContentWidget(CreateEmptyContent());
	}
}

const FSlateBrush* SArticyObjectToolTip::GetTooltipImage() const
{
	return &TooltipBrush;
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>// Time:  O(m * n)
// Space: O(m)

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    int backPack(int m, vector<int> A) {
        // table[i][j] denotes whether using the first elements
        // could fulfill size j.
        vector<vector<bool>> table(2, vector<bool>(m + 1, false));
        int max_size = 0;
        table[0][0] = true;

        for (int i = 1; i <= A.size(); ++i) {
            table[i % 2][0] = true;
            for (int j = 1; j <= m; ++j) {
                // If first i - 1 elements could fulfill the backpack, then
                // first i elements would also do.
                table[i % 2][j] = table[(i - 1) % 2][j];

                // Using the ith element to fulfill the backpack.
                if (j >= A[i - 1]) {
                    table[i % 2][j] = table[i % 2][j]
                    || table[(i - 1) % 2][j - A[i - 1]];
                }

                // If it fulfills size j, update max size.
                if (table[i % 2][j]) {
                    max_size = max(max_size, j);
                }
            }
        }

        return max_size;
    }
};
<commit_msg>Update backpack.cpp<commit_after>// Time:  O(m * n)
// Space: O(m)

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    int backPack(int m, vector<int> A) {
        // table[i][j] denotes whether using the first i elements
        // could fulfill size j.
        vector<vector<bool>> table(2, vector<bool>(m + 1, false));
        int max_size = 0;
        table[0][0] = true;

        for (int i = 1; i <= A.size(); ++i) {
            table[i % 2][0] = true;
            for (int j = 1; j <= m; ++j) {
                // If first i - 1 elements could fulfill the backpack, then
                // first i elements would also do.
                table[i % 2][j] = table[(i - 1) % 2][j];

                // Using the ith element to fulfill the backpack.
                if (j >= A[i - 1]) {
                    table[i % 2][j] = table[i % 2][j]
                    || table[(i - 1) % 2][j - A[i - 1]];
                }

                // If it fulfills size j, update max size.
                if (table[i % 2][j]) {
                    max_size = max(max_size, j);
                }
            }
        }

        return max_size;
    }
};
<|endoftext|>


<commit_before>#include "SeqProjectHeaders.h"
#include "SeqPlayer.h"
#include "SeqList.h"
#include "SeqSerializer.h"
#include "SeqString.h"
#include "SeqTime.h"

SeqScene::SeqScene(int id, const char *sceneName) :
	id(id),
	lastClip(nullptr),
	nextActionId(0)
{
	name = SeqString::Copy(sceneName);
	channels = new SeqList<SeqChannel*>();
	clipGroups = new SeqList <SeqClipGroup*>();
	player = new SeqPlayer(this);
}

SeqScene::SeqScene(SeqSerializer *serializer):
	id(0),
	name(nullptr),
	lastClip(nullptr),
	nextActionId(0)
{
	channels = new SeqList<SeqChannel*>();
	clipGroups = new SeqList<SeqClipGroup*>();
	Deserialize(serializer);
	player = new SeqPlayer(this);
}

SeqScene::~SeqScene()
{
	for (int i = 0; i < channels->Count(); i++)
		delete channels->Get(i);
	delete channels;
	delete clipGroups;
	delete[] name;
}

void SeqScene::AddChannel(SeqChannelType type, const char *name)
{
	SeqChannel *channel = new SeqChannel(this, name, type);
	AddChannel(channel);
}

void SeqScene::AddChannel(SeqChannel *channel)
{
	channels->Add(channel);
	if (channel->actionId == -1)
		channel->actionId = NextActionId();
	else if (channel->actionId >= nextActionId)
		nextActionId = channel->actionId + 1;
}

void SeqScene::RemoveChannel(const int index)
{
	delete channels->Get(index);
	channels->RemoveAt(index);
}

int SeqScene::ChannelCount()
{
	return channels->Count();
}

SeqChannel* SeqScene::GetChannel(const int index)
{
	return channels->Get(index);
}

SeqChannel* SeqScene::GetChannelByActionId(const int id)
{
	return GetChannel(GetChannelIndexByActionId(id));
}

int SeqScene::GetChannelIndexByActionId(const int id)
{
	for (int i = 0; i < channels->Count(); i++)
		if (channels->Get(i)->actionId == id)
			return i;
	return -1;
}

void SeqScene::AddClipGroup()
{
	SeqClipGroup *clipGroup = new SeqClipGroup(this);
	AddClipGroup(clipGroup);
}

void SeqScene::AddClipGroup(SeqClipGroup *clipGroup)
{
	clipGroups->Add(clipGroup);
	if (clipGroup->actionId == -1)
		clipGroup->actionId = NextActionId();
	else if (clipGroup->actionId >= nextActionId)
		nextActionId = clipGroup->actionId + 1;
}

void SeqScene::RemoveClipGroup(const int index)
{
	delete clipGroups->Get(index);
	clipGroups->RemoveAt(index);
}

void SeqScene::RemoveClipGroup(SeqClipGroup *group)
{
	int index = clipGroups->IndexOf(group);
	RemoveClipGroup(index);
}

int SeqScene::ClipGroupCount()
{
	return clipGroups->Count();
}

SeqClipGroup* SeqScene::GetClipGroup(const int index)
{
	return clipGroups->Get(index);
}

SeqClipGroup* SeqScene::GetClipGroupByActionId(const int id)
{
	return GetClipGroup(GetClipGroupIndexByActionId(id));
}

int SeqScene::GetClipGroupIndexByActionId(const int id)
{
	for (int i = 0; i < clipGroups->Count(); i++)
		if (clipGroups->Get(i)->actionId == id)
			return i;
	return -1;
}

void SeqScene::RefreshLastClip()
{
	lastClip = nullptr;
	int64_t latestTime = 0;
	for (int i = 0; i < channels->Count(); i++)
	{
		SeqChannel *channel = channels->Get(i);
		for (int j = 0; j < channel->ClipCount(); j++)
		{
			SeqClip *clip = channel->GetClip(j);
			int64_t rightTime = clip->location.rightTime;
			if (rightTime > latestTime)
			{
				latestTime = rightTime;
				lastClip = clip;
			}
		}
	}
}

int64_t SeqScene::GetLength()
{
	if (lastClip != nullptr)
		return lastClip->location.rightTime;
	else
		return SEQ_TIME_BASE;
}

int SeqScene::NextActionId()
{
	return nextActionId++;
}

void SeqScene::Serialize(SeqSerializer *serializer)
{
	serializer->Write(id);
	serializer->Write(name);
	serializer->Write(channels->Count());
	for (int i = 0; i < channels->Count(); i++)
		channels->Get(i)->Serialize(serializer);
	serializer->Write(clipGroups->Count());
	for (int i = 0; i < clipGroups->Count(); i++)
		clipGroups->Get(i)->Serialize(serializer);
}

void SeqScene::Deserialize(SeqSerializer *serializer)
{
	id = serializer->ReadInt();
	name = serializer->ReadString();
	int channelCount = serializer->ReadInt();
	for (int i = 0; i < channelCount; i++)
	{
		SeqChannel *channel = new SeqChannel(this, serializer);
		AddChannel(channel);
	}
	int clipGroupCount = serializer->ReadInt();
	for (int i = 0; i < clipGroupCount; i++)
	{
		SeqClipGroup *clipGroup = new SeqClipGroup(this, serializer);
		AddClipGroup(clipGroup);
	}
	RefreshLastClip();
}
<commit_msg>FIxed memory leak.<commit_after>#include "SeqProjectHeaders.h"
#include "SeqPlayer.h"
#include "SeqList.h"
#include "SeqSerializer.h"
#include "SeqString.h"
#include "SeqTime.h"

SeqScene::SeqScene(int id, const char *sceneName) :
	id(id),
	lastClip(nullptr),
	nextActionId(0)
{
	name = SeqString::Copy(sceneName);
	channels = new SeqList<SeqChannel*>();
	clipGroups = new SeqList <SeqClipGroup*>();
	player = new SeqPlayer(this);
}

SeqScene::SeqScene(SeqSerializer *serializer):
	id(0),
	name(nullptr),
	lastClip(nullptr),
	nextActionId(0)
{
	channels = new SeqList<SeqChannel*>();
	clipGroups = new SeqList<SeqClipGroup*>();
	Deserialize(serializer);
	player = new SeqPlayer(this);
}

SeqScene::~SeqScene()
{
	delete player;
	for (int i = 0; i < channels->Count(); i++)
		delete channels->Get(i);
	delete channels;
	delete clipGroups;
	delete[] name;
}

void SeqScene::AddChannel(SeqChannelType type, const char *name)
{
	SeqChannel *channel = new SeqChannel(this, name, type);
	AddChannel(channel);
}

void SeqScene::AddChannel(SeqChannel *channel)
{
	channels->Add(channel);
	if (channel->actionId == -1)
		channel->actionId = NextActionId();
	else if (channel->actionId >= nextActionId)
		nextActionId = channel->actionId + 1;
}

void SeqScene::RemoveChannel(const int index)
{
	delete channels->Get(index);
	channels->RemoveAt(index);
}

int SeqScene::ChannelCount()
{
	return channels->Count();
}

SeqChannel* SeqScene::GetChannel(const int index)
{
	return channels->Get(index);
}

SeqChannel* SeqScene::GetChannelByActionId(const int id)
{
	return GetChannel(GetChannelIndexByActionId(id));
}

int SeqScene::GetChannelIndexByActionId(const int id)
{
	for (int i = 0; i < channels->Count(); i++)
		if (channels->Get(i)->actionId == id)
			return i;
	return -1;
}

void SeqScene::AddClipGroup()
{
	SeqClipGroup *clipGroup = new SeqClipGroup(this);
	AddClipGroup(clipGroup);
}

void SeqScene::AddClipGroup(SeqClipGroup *clipGroup)
{
	clipGroups->Add(clipGroup);
	if (clipGroup->actionId == -1)
		clipGroup->actionId = NextActionId();
	else if (clipGroup->actionId >= nextActionId)
		nextActionId = clipGroup->actionId + 1;
}

void SeqScene::RemoveClipGroup(const int index)
{
	delete clipGroups->Get(index);
	clipGroups->RemoveAt(index);
}

void SeqScene::RemoveClipGroup(SeqClipGroup *group)
{
	int index = clipGroups->IndexOf(group);
	RemoveClipGroup(index);
}

int SeqScene::ClipGroupCount()
{
	return clipGroups->Count();
}

SeqClipGroup* SeqScene::GetClipGroup(const int index)
{
	return clipGroups->Get(index);
}

SeqClipGroup* SeqScene::GetClipGroupByActionId(const int id)
{
	return GetClipGroup(GetClipGroupIndexByActionId(id));
}

int SeqScene::GetClipGroupIndexByActionId(const int id)
{
	for (int i = 0; i < clipGroups->Count(); i++)
		if (clipGroups->Get(i)->actionId == id)
			return i;
	return -1;
}

void SeqScene::RefreshLastClip()
{
	lastClip = nullptr;
	int64_t latestTime = 0;
	for (int i = 0; i < channels->Count(); i++)
	{
		SeqChannel *channel = channels->Get(i);
		for (int j = 0; j < channel->ClipCount(); j++)
		{
			SeqClip *clip = channel->GetClip(j);
			int64_t rightTime = clip->location.rightTime;
			if (rightTime > latestTime)
			{
				latestTime = rightTime;
				lastClip = clip;
			}
		}
	}
}

int64_t SeqScene::GetLength()
{
	if (lastClip != nullptr)
		return lastClip->location.rightTime;
	else
		return SEQ_TIME_BASE;
}

int SeqScene::NextActionId()
{
	return nextActionId++;
}

void SeqScene::Serialize(SeqSerializer *serializer)
{
	serializer->Write(id);
	serializer->Write(name);
	serializer->Write(channels->Count());
	for (int i = 0; i < channels->Count(); i++)
		channels->Get(i)->Serialize(serializer);
	serializer->Write(clipGroups->Count());
	for (int i = 0; i < clipGroups->Count(); i++)
		clipGroups->Get(i)->Serialize(serializer);
}

void SeqScene::Deserialize(SeqSerializer *serializer)
{
	id = serializer->ReadInt();
	name = serializer->ReadString();
	int channelCount = serializer->ReadInt();
	for (int i = 0; i < channelCount; i++)
	{
		SeqChannel *channel = new SeqChannel(this, serializer);
		AddChannel(channel);
	}
	int clipGroupCount = serializer->ReadInt();
	for (int i = 0; i < clipGroupCount; i++)
	{
		SeqClipGroup *clipGroup = new SeqClipGroup(this, serializer);
		AddClipGroup(clipGroup);
	}
	RefreshLastClip();
}
<|endoftext|>