<commit_before>#include "Sorter.h"

#include <document-manager/DocumentManager.h>
#include <index-manager/IndexManager.h>
#include <mining-manager/faceted-submanager/ctr_manager.h>
#include <bundles/index/IndexBundleConfiguration.h>
#include <common/PropSharedLockSet.h>

namespace sf1r
{

const char SortPropertyCache::Separator[] = {'-', '~', ','};

SortProperty::SortProperty(const SortProperty& src)
    : property_(src.property_)
    , propertyDataType_(src.propertyDataType_)
    , type_(src.type_)
    , reverse_(src.reverse_)
    , pComparator_(src.pComparator_)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(AUTO)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}
SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(CUSTOM)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::~SortProperty()
{
    if (pComparator_)
        delete pComparator_;
}

SortPropertyCache::SortPropertyCache(DocumentManager* pDocumentManager, IndexManager* pIndexer, IndexBundleConfiguration* config)
    : pDocumentManager_(pDocumentManager)
    , pIndexer_(pIndexer)
    , pCTRManager_(NULL)
    , updateInterval_(config->sortCacheUpdateInterval_)
    , dirty_(true)
    , config_(config)
{
    std::cout << "SortPropertyCache::updateInterval_ = " << updateInterval_ << std::endl;
}

void SortPropertyCache::setCtrManager(faceted::CTRManager* pCTRManager)
{
    pCTRManager_ = pCTRManager;
}

void SortPropertyCache::loadSortData(const std::string& property, PropertyDataType type)
{
    boost::shared_ptr<NumericPropertyTableBase>& numericPropertyTable = sortDataCache_[property];
    if (type == STRING_PROPERTY_TYPE)
    {
        std::size_t size = pIndexer_->getIndexReader()->maxDoc();
        if (size)
        {
            pIndexer_->convertStringPropertyDataForSorting(property, numericPropertyTable);
        }
    }
    else
    {
        boost::shared_ptr<NumericPropertyTableBase>& tempTable = pDocumentManager_->getNumericPropertyTable(property);
        if (tempTable)
        {
            numericPropertyTable = tempTable;
        }
        else
        {
            switch (type)
            {
            case INT32_PROPERTY_TYPE:
            case INT8_PROPERTY_TYPE:
            case INT16_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<int32_t>(property, type, numericPropertyTable);
                break;

            case FLOAT_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<float>(property, type, numericPropertyTable);
                break;

            case INT64_PROPERTY_TYPE:
            case DATETIME_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<int64_t>(property, type, numericPropertyTable);
                break;

            case DOUBLE_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<double>(property, type, numericPropertyTable);
                break;

            default:
                break;
            }
        }
    }
}

boost::shared_ptr<NumericPropertyTableBase>& SortPropertyCache::getSortPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);
    if (dirty_)
    {
        for (SortDataCache::iterator iter = sortDataCache_.begin();
                iter != sortDataCache_.end(); ++iter)
        {
            LOG(INFO) << "dirty sort data cache on property: " << iter->first;
            if (iter->second) loadSortData(iter->first, iter->second->getType());
        }
        dirty_ = false;
    }

    SortDataCache::iterator iter = sortDataCache_.find(propertyName);
    if (iter == sortDataCache_.end() || !iter->second)
    {
        LOG(INFO) << "first load sort data cache on property: " << propertyName;
        loadSortData(propertyName, propertyType);
    }

    return sortDataCache_[propertyName];
}

boost::shared_ptr<NumericPropertyTableBase>& SortPropertyCache::getCTRPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);

    boost::shared_ptr<NumericPropertyTableBase>& numericPropertyTable = sortDataCache_[propertyName];
    if (!numericPropertyTable)
        pCTRManager_->loadCtrData(numericPropertyTable);

    return numericPropertyTable;
}

SortPropertyComparator* SortPropertyCache::getComparator(
    SortProperty* pSortProperty,
    PropSharedLockSet& propSharedLockSet)
{
    SortProperty::SortPropertyType propSortType = pSortProperty->getType();
    const std::string& propName = pSortProperty->getProperty();
    const PropertyDataType propDataType = pSortProperty->getPropertyDataType();

    boost::shared_ptr<NumericPropertyTableBase> numericPropertyTable;
    if (propSortType == SortProperty::AUTO)
    {
        numericPropertyTable = getSortPropertyData(propName, propDataType);
    }
    else if (propSortType == SortProperty::CTR)
    {
        if (pCTRManager_)
            numericPropertyTable = getCTRPropertyData(propName, propDataType);
    }
    else
    {
        // to extend
    }

    if (numericPropertyTable)
    {
        propSharedLockSet.insertSharedLock(numericPropertyTable.get());
        return new SortPropertyComparator(numericPropertyTable);
    }

    return NULL;
}

Sorter::Sorter(SortPropertyCache* pCache)
    : pCache_(pCache)
    , ppSortProperties_(0)
    , reverseMul_(0)
{
}

Sorter::~Sorter()
{
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter)
        delete *iter;
    if (ppSortProperties_) delete[] ppSortProperties_;
    if (reverseMul_) delete[] reverseMul_;
}

void Sorter::addSortProperty(const string& property, PropertyDataType propertyType, bool reverse)
{
    SortProperty* pSortProperty = new SortProperty(property, propertyType, reverse);
    sortProperties_.push_back(pSortProperty);
}

void Sorter::addSortProperty(SortProperty* pSortProperty)
{
    sortProperties_.push_back(pSortProperty);
}

void Sorter::getComparators(PropSharedLockSet& propSharedLockSet)
{
    SortProperty* pSortProperty;
    nNumProperties_ = sortProperties_.size();
    ppSortProperties_ = new SortProperty*[nNumProperties_];
    size_t i = 0;
    size_t numOfInValidComparators = 0;
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter, ++i)
    {
        pSortProperty = *iter;
        ppSortProperties_[i] = pSortProperty;
        if (pSortProperty)
        {
            switch (pSortProperty->getType())
            {
            case SortProperty::SCORE:
                pSortProperty->pComparator_= new SortPropertyComparator();
                break;
            case SortProperty::AUTO:
                if (!pSortProperty->pComparator_)
                    pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty,
                                                                         propSharedLockSet);
                if (!pSortProperty->pComparator_)
                    ++numOfInValidComparators;
                break;
            case SortProperty::CUSTOM:
                pSortProperty->pComparator_ = new SortPropertyComparator(CUSTOM_RANKING_PROPERTY_TYPE);
                break;
            case SortProperty::CTR:
                pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty,
                                                                     propSharedLockSet);
                if (!pSortProperty->pComparator_)
                    ++numOfInValidComparators;
                break;
            }
        }
    }
    if (numOfInValidComparators > 0)
    {
        SortProperty** ppSortProperties = NULL;
        if (numOfInValidComparators == nNumProperties_)
        {
            nNumProperties_ = 1;
            ppSortProperties = new SortProperty*[nNumProperties_];
            SortProperty* pSortProperty = new SortProperty("RANK", UNKNOWN_DATA_PROPERTY_TYPE);
            pSortProperty->pComparator_ = new SortPropertyComparator();
            ppSortProperties[0] = pSortProperty;
            sortProperties_.push_back(pSortProperty);
        }
        else
        {
            ppSortProperties = new SortProperty*[nNumProperties_];
            size_t j = 0;
            for (i = 0; i < nNumProperties_; ++i)
            {
                SortProperty* pSortProperty = ppSortProperties_[i];
                if (pSortProperty->pComparator_)
                {
                    ppSortProperties[j++] = pSortProperty;
                }
            }
            nNumProperties_ = j;
        }
        delete [] ppSortProperties_;
        ppSortProperties_ = ppSortProperties;
    }
    reverseMul_ = new int[nNumProperties_];
    for (i = 0; i < nNumProperties_; ++i)
    {
        reverseMul_[i] = ppSortProperties_[i]->isReverse() ? -1 : 1;
    }
}

}
<commit_msg>_ctr should be neglected in getSortPropertyData, or else:<commit_after>#include "Sorter.h"

#include <document-manager/DocumentManager.h>
#include <index-manager/IndexManager.h>
#include <mining-manager/faceted-submanager/ctr_manager.h>
#include <bundles/index/IndexBundleConfiguration.h>
#include <common/PropSharedLockSet.h>

namespace sf1r
{

const char SortPropertyCache::Separator[] = {'-', '~', ','};

SortProperty::SortProperty(const SortProperty& src)
    : property_(src.property_)
    , propertyDataType_(src.propertyDataType_)
    , type_(src.type_)
    , reverse_(src.reverse_)
    , pComparator_(src.pComparator_)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(AUTO)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}
SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(CUSTOM)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::~SortProperty()
{
    if (pComparator_)
        delete pComparator_;
}

SortPropertyCache::SortPropertyCache(DocumentManager* pDocumentManager, IndexManager* pIndexer, IndexBundleConfiguration* config)
    : pDocumentManager_(pDocumentManager)
    , pIndexer_(pIndexer)
    , pCTRManager_(NULL)
    , updateInterval_(config->sortCacheUpdateInterval_)
    , dirty_(true)
    , config_(config)
{
    std::cout << "SortPropertyCache::updateInterval_ = " << updateInterval_ << std::endl;
}

void SortPropertyCache::setCtrManager(faceted::CTRManager* pCTRManager)
{
    pCTRManager_ = pCTRManager;
}

void SortPropertyCache::loadSortData(const std::string& property, PropertyDataType type)
{
    boost::shared_ptr<NumericPropertyTableBase>& numericPropertyTable = sortDataCache_[property];
    if (type == STRING_PROPERTY_TYPE)
    {
        std::size_t size = pIndexer_->getIndexReader()->maxDoc();
        if (size)
        {
            pIndexer_->convertStringPropertyDataForSorting(property, numericPropertyTable);
        }
    }
    else
    {
        boost::shared_ptr<NumericPropertyTableBase>& tempTable = pDocumentManager_->getNumericPropertyTable(property);
        if (tempTable)
        {
            numericPropertyTable = tempTable;
        }
        else
        {
            switch (type)
            {
            case INT32_PROPERTY_TYPE:
            case INT8_PROPERTY_TYPE:
            case INT16_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<int32_t>(property, type, numericPropertyTable);
                break;

            case FLOAT_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<float>(property, type, numericPropertyTable);
                break;

            case INT64_PROPERTY_TYPE:
            case DATETIME_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<int64_t>(property, type, numericPropertyTable);
                break;

            case DOUBLE_PROPERTY_TYPE:
                pIndexer_->loadPropertyDataForSorting<double>(property, type, numericPropertyTable);
                break;

            default:
                break;
            }
        }
    }
}

boost::shared_ptr<NumericPropertyTableBase>& SortPropertyCache::getSortPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);
    if (dirty_)
    {
        for (SortDataCache::iterator iter = sortDataCache_.begin();
                iter != sortDataCache_.end(); ++iter)
        {
            LOG(INFO) << "dirty sort data cache on property: " << iter->first;
            if (iter->first == faceted::CTRManager::kCtrPropName) continue;
            if (iter->second) loadSortData(iter->first, iter->second->getType());
        }
        dirty_ = false;
    }

    SortDataCache::iterator iter = sortDataCache_.find(propertyName);
    if (iter == sortDataCache_.end() || !iter->second)
    {
        LOG(INFO) << "first load sort data cache on property: " << propertyName;
        loadSortData(propertyName, propertyType);
    }

    return sortDataCache_[propertyName];
}

boost::shared_ptr<NumericPropertyTableBase>& SortPropertyCache::getCTRPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);

    boost::shared_ptr<NumericPropertyTableBase>& numericPropertyTable = sortDataCache_[propertyName];
    if (!numericPropertyTable)
        pCTRManager_->loadCtrData(numericPropertyTable);

    return numericPropertyTable;
}

SortPropertyComparator* SortPropertyCache::getComparator(
    SortProperty* pSortProperty,
    PropSharedLockSet& propSharedLockSet)
{
    SortProperty::SortPropertyType propSortType = pSortProperty->getType();
    const std::string& propName = pSortProperty->getProperty();
    const PropertyDataType propDataType = pSortProperty->getPropertyDataType();

    boost::shared_ptr<NumericPropertyTableBase> numericPropertyTable;
    if (propSortType == SortProperty::AUTO)
    {
        numericPropertyTable = getSortPropertyData(propName, propDataType);
    }
    else if (propSortType == SortProperty::CTR)
    {
        if (pCTRManager_)
            numericPropertyTable = getCTRPropertyData(propName, propDataType);
    }
    else
    {
        // to extend
    }

    if (numericPropertyTable)
    {
        propSharedLockSet.insertSharedLock(numericPropertyTable.get());
        return new SortPropertyComparator(numericPropertyTable);
    }

    return NULL;
}

Sorter::Sorter(SortPropertyCache* pCache)
    : pCache_(pCache)
    , ppSortProperties_(0)
    , reverseMul_(0)
{
}

Sorter::~Sorter()
{
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter)
        delete *iter;
    if (ppSortProperties_) delete[] ppSortProperties_;
    if (reverseMul_) delete[] reverseMul_;
}

void Sorter::addSortProperty(const string& property, PropertyDataType propertyType, bool reverse)
{
    SortProperty* pSortProperty = new SortProperty(property, propertyType, reverse);
    sortProperties_.push_back(pSortProperty);
}

void Sorter::addSortProperty(SortProperty* pSortProperty)
{
    sortProperties_.push_back(pSortProperty);
}

void Sorter::getComparators(PropSharedLockSet& propSharedLockSet)
{
    SortProperty* pSortProperty;
    nNumProperties_ = sortProperties_.size();
    ppSortProperties_ = new SortProperty*[nNumProperties_];
    size_t i = 0;
    size_t numOfInValidComparators = 0;
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter, ++i)
    {
        pSortProperty = *iter;
        ppSortProperties_[i] = pSortProperty;
        if (pSortProperty)
        {
            switch (pSortProperty->getType())
            {
            case SortProperty::SCORE:
                pSortProperty->pComparator_= new SortPropertyComparator();
                break;
            case SortProperty::AUTO:
                if (!pSortProperty->pComparator_)
                    pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty,
                                                                         propSharedLockSet);
                if (!pSortProperty->pComparator_)
                    ++numOfInValidComparators;
                break;
            case SortProperty::CUSTOM:
                pSortProperty->pComparator_ = new SortPropertyComparator(CUSTOM_RANKING_PROPERTY_TYPE);
                break;
            case SortProperty::CTR:
                pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty,
                                                                     propSharedLockSet);
                if (!pSortProperty->pComparator_)
                    ++numOfInValidComparators;
                break;
            }
        }
    }
    if (numOfInValidComparators > 0)
    {
        SortProperty** ppSortProperties = NULL;
        if (numOfInValidComparators == nNumProperties_)
        {
            nNumProperties_ = 1;
            ppSortProperties = new SortProperty*[nNumProperties_];
            SortProperty* pSortProperty = new SortProperty("RANK", UNKNOWN_DATA_PROPERTY_TYPE);
            pSortProperty->pComparator_ = new SortPropertyComparator();
            ppSortProperties[0] = pSortProperty;
            sortProperties_.push_back(pSortProperty);
        }
        else
        {
            ppSortProperties = new SortProperty*[nNumProperties_];
            size_t j = 0;
            for (i = 0; i < nNumProperties_; ++i)
            {
                SortProperty* pSortProperty = ppSortProperties_[i];
                if (pSortProperty->pComparator_)
                {
                    ppSortProperties[j++] = pSortProperty;
                }
            }
            nNumProperties_ = j;
        }
        delete [] ppSortProperties_;
        ppSortProperties_ = ppSortProperties;
    }
    reverseMul_ = new int[nNumProperties_];
    for (i = 0; i < nNumProperties_; ++i)
    {
        reverseMul_[i] = ppSortProperties_[i]->isReverse() ? -1 : 1;
    }
}

}
<|endoftext|>


<commit_before>#include "Metalink4Writer.hpp"

Metalink4Writer::Metalink4Writer(MetalinkEditor& editor)
    : editor_(editor)
{
}

Metalink4Writer::~Metalink4Writer()
{
    if(out_.is_open()) out_.close();
}

void Metalink4Writer::save(const wxString& filename)
{
    using std::ofstream;
    out_.open(filename.mb_str(wxConvFile),
              ofstream::out | ofstream::binary | ofstream::trunc);
    indent_ = 0;
    write(wxT("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"));
    write(wxT("<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">\n"));
    indent_++;
    const std::vector<MetalinkFile>& files = editor_.get_files();
    for(std::vector<MetalinkFile>::const_iterator i = files.begin(),
            eoi = files.end(); i != eoi; ++i) {
        write(*i);
    }
    indent_--;
    write(wxT("</metalink>\n"));
}

void Metalink4Writer::write(const MetalinkFile& file)
{
    start(wxT("file"));
    addattr(wxT("name"), file.get_filename());
    close_start();
    const std::vector<MetalinkSource>& sources = file.get_sources();
    for(std::vector<MetalinkSource>::const_iterator i = sources.begin(),
            eoi = sources.end(); i != eoi; ++i) {
        write(*i);
    }
    end(wxT("file"));
}

void Metalink4Writer::write(const MetalinkSource& source)
{
    start(wxT("url"));
    if(!source.get_location().empty()) {
        addattr(wxT("location"), source.get_location());
    }
    if(!source.get_prioritystr().empty()) {
        addattr(wxT("priority"), source.get_prioritystr());
    }
    end(wxT("url"), source.get_uri());
}

void Metalink4Writer::write(const wxString& data, bool indent)
{
    if(indent) {
        for(int i = 0; i < indent_; i++) {
            out_ << "    ";
        }
    }
    out_ << data.mb_str(wxConvUTF8);
}

void Metalink4Writer::start(const wxString& element)
{
    write(wxT("<"));
    write(element, false);
}

void Metalink4Writer::close_start()
{
    write(wxT(">\n"), false);
    indent_++;
}

namespace {
// Escapes characters not allowed in XML documents and returns new
// escaped string.
wxString xml_escape(const wxString& src)
{
    wxString dest;
    for(wxString::const_iterator i = src.begin(), eoi = src.end();
            i != eoi; ++i) {
        const wxChar ch = *i;
        if(ch == wxT('<')) {
            dest += wxT("<");
        } else if(ch == wxT('>')) {
            dest += wxT(">");
        } else if(ch == wxT('&')) {
            dest += wxT("&");
        } else if(ch == wxT('\'')) {
            dest += wxT("'");
        } else if(ch == wxT('"')) {
            dest += wxT(""");
        } else {
            dest += ch;
        }
    }
    return dest;
}
}

void Metalink4Writer::end(const wxString& element, const wxString& value)
{
    write(wxT(">"), false);
    write(xml_escape(value), false);
    write(wxT("</"), false);
    write(element, false);
    write(wxT(">\n"), false);
}

void Metalink4Writer::end(const wxString& element)
{
    indent_--;
    write(wxT("</"));
    write(element, false);
    write(wxT(">\n"), false);
}

void Metalink4Writer::addattr(const wxString& name, const wxString& value)
{
    write(wxT(" "), false);
    write(name, false);
    write(wxT("=\""), false);
    write(xml_escape(value), false);
    write(wxT("\""), false);
}
<commit_msg>Closing stream is handled in std::ofstream dtor.<commit_after>#include "Metalink4Writer.hpp"

Metalink4Writer::Metalink4Writer(MetalinkEditor& editor)
    : editor_(editor)
{
}

Metalink4Writer::~Metalink4Writer()
{
}

void Metalink4Writer::save(const wxString& filename)
{
    using std::ofstream;
    out_.open(filename.mb_str(wxConvFile),
              ofstream::out | ofstream::binary | ofstream::trunc);
    indent_ = 0;
    write(wxT("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"));
    write(wxT("<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">\n"));
    indent_++;
    const std::vector<MetalinkFile>& files = editor_.get_files();
    for(std::vector<MetalinkFile>::const_iterator i = files.begin(),
            eoi = files.end(); i != eoi; ++i) {
        write(*i);
    }
    indent_--;
    write(wxT("</metalink>\n"));
}

void Metalink4Writer::write(const MetalinkFile& file)
{
    start(wxT("file"));
    addattr(wxT("name"), file.get_filename());
    close_start();
    const std::vector<MetalinkSource>& sources = file.get_sources();
    for(std::vector<MetalinkSource>::const_iterator i = sources.begin(),
            eoi = sources.end(); i != eoi; ++i) {
        write(*i);
    }
    end(wxT("file"));
}

void Metalink4Writer::write(const MetalinkSource& source)
{
    start(wxT("url"));
    if(!source.get_location().empty()) {
        addattr(wxT("location"), source.get_location());
    }
    if(!source.get_prioritystr().empty()) {
        addattr(wxT("priority"), source.get_prioritystr());
    }
    end(wxT("url"), source.get_uri());
}

void Metalink4Writer::write(const wxString& data, bool indent)
{
    if(indent) {
        for(int i = 0; i < indent_; i++) {
            out_ << "    ";
        }
    }
    out_ << data.mb_str(wxConvUTF8);
}

void Metalink4Writer::start(const wxString& element)
{
    write(wxT("<"));
    write(element, false);
}

void Metalink4Writer::close_start()
{
    write(wxT(">\n"), false);
    indent_++;
}

namespace {
// Escapes characters not allowed in XML documents and returns new
// escaped string.
wxString xml_escape(const wxString& src)
{
    wxString dest;
    for(wxString::const_iterator i = src.begin(), eoi = src.end();
            i != eoi; ++i) {
        const wxChar ch = *i;
        if(ch == wxT('<')) {
            dest += wxT("<");
        } else if(ch == wxT('>')) {
            dest += wxT(">");
        } else if(ch == wxT('&')) {
            dest += wxT("&");
        } else if(ch == wxT('\'')) {
            dest += wxT("'");
        } else if(ch == wxT('"')) {
            dest += wxT(""");
        } else {
            dest += ch;
        }
    }
    return dest;
}
}

void Metalink4Writer::end(const wxString& element, const wxString& value)
{
    write(wxT(">"), false);
    write(xml_escape(value), false);
    write(wxT("</"), false);
    write(element, false);
    write(wxT(">\n"), false);
}

void Metalink4Writer::end(const wxString& element)
{
    indent_--;
    write(wxT("</"));
    write(element, false);
    write(wxT(">\n"), false);
}

void Metalink4Writer::addattr(const wxString& name, const wxString& value)
{
    write(wxT(" "), false);
    write(name, false);
    write(wxT("=\""), false);
    write(xml_escape(value), false);
    write(wxT("\""), false);
}
<|endoftext|>


<commit_before>//===--- CommandLine.cpp - OS-specific command line arguments -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2016 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
//
//===----------------------------------------------------------------------===//
//
// OS-specific command line argument handling is defined here.
//
//===----------------------------------------------------------------------===//

#include <vector>
#include <string>
#include <cassert>
#include <climits>
#include <cstdarg>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "swift/Runtime/Debug.h"

#include "../SwiftShims/RuntimeStubs.h"
#include "../SwiftShims/GlobalObjects.h"

// Backing storage for overrides of `Swift.Process.arguments`.
static char **_swift_stdlib_ProcessOverrideUnsafeArgv = nullptr;
static int _swift_stdlib_ProcessOverrideUnsafeArgc = 0;

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" void _swift_stdlib_overrideUnsafeArgvArgc(char **argv, int argc) {
  _swift_stdlib_ProcessOverrideUnsafeArgv = argv;
  _swift_stdlib_ProcessOverrideUnsafeArgc = argc;
}

#if defined(__APPLE__)
// NOTE: forward declare this rather than including crt_externs.h as not all
// SDKs provide it
extern "C" char ***_NSGetArgv(void);
extern "C" int *_NSGetArgc(void);

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  assert(outArgLen != nullptr);

  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  *outArgLen = *_NSGetArgc();
  return *_NSGetArgv();
}
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__)
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  assert(outArgLen != nullptr);

  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  FILE *cmdline = fopen("/proc/self/cmdline", "rb");
  if (!cmdline) {
    swift::fatalError(0,
            "fatal error: Unable to open interface to '/proc/self/cmdline'.\n");
  }
  char *arg = nullptr;
  size_t size = 0;
  std::vector<char *> argvec;
  while (getdelim(&arg, &size, 0, cmdline) != -1) {
    argvec.push_back(strdup(arg));
  }
  if (arg) {
    free(arg);
  }
  fclose(cmdline);
  *outArgLen = argvec.size();
  char **outBuf = (char **)calloc(argvec.size() + 1, sizeof(char *));
  std::copy(argvec.begin(), argvec.end(), outBuf);
  outBuf[argvec.size()] = nullptr;

  return outBuf;
}
#elif defined (_MSC_VER)
extern int *__argc;
extern char **__argv;

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  assert(outArgLen != nullptr);

  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  *outArgLen = __argc;
  return __argv;
}
#else // __ANDROID__; Add your favorite arch's command line arg grabber here.
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  swift::fatalError(0,
      "fatal error: Command line arguments not supported on this platform.\n");
}
#endif

<commit_msg>stdlib: repair windows build<commit_after>//===--- CommandLine.cpp - OS-specific command line arguments -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2016 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
//
//===----------------------------------------------------------------------===//
//
// OS-specific command line argument handling is defined here.
//
//===----------------------------------------------------------------------===//

#include <vector>
#include <string>
#include <cassert>
#include <climits>
#include <cstdarg>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "swift/Runtime/Debug.h"

#include "../SwiftShims/RuntimeStubs.h"
#include "../SwiftShims/GlobalObjects.h"

// Backing storage for overrides of `Swift.Process.arguments`.
static char **_swift_stdlib_ProcessOverrideUnsafeArgv = nullptr;
static int _swift_stdlib_ProcessOverrideUnsafeArgc = 0;

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" void _swift_stdlib_overrideUnsafeArgvArgc(char **argv, int argc) {
  _swift_stdlib_ProcessOverrideUnsafeArgv = argv;
  _swift_stdlib_ProcessOverrideUnsafeArgc = argc;
}

#if defined(__APPLE__)
// NOTE: forward declare this rather than including crt_externs.h as not all
// SDKs provide it
extern "C" char ***_NSGetArgv(void);
extern "C" int *_NSGetArgc(void);

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  assert(outArgLen != nullptr);

  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  *outArgLen = *_NSGetArgc();
  return *_NSGetArgv();
}
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__)
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  assert(outArgLen != nullptr);

  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  FILE *cmdline = fopen("/proc/self/cmdline", "rb");
  if (!cmdline) {
    swift::fatalError(0,
            "fatal error: Unable to open interface to '/proc/self/cmdline'.\n");
  }
  char *arg = nullptr;
  size_t size = 0;
  std::vector<char *> argvec;
  while (getdelim(&arg, &size, 0, cmdline) != -1) {
    argvec.push_back(strdup(arg));
  }
  if (arg) {
    free(arg);
  }
  fclose(cmdline);
  *outArgLen = argvec.size();
  char **outBuf = (char **)calloc(argvec.size() + 1, sizeof(char *));
  std::copy(argvec.begin(), argvec.end(), outBuf);
  outBuf[argvec.size()] = nullptr;

  return outBuf;
}
#elif defined (_MSC_VER)
#include <stdlib.h>

SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  assert(outArgLen != nullptr);

  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  *outArgLen = __argc;
  return __argv;
}
#else // __ANDROID__; Add your favorite arch's command line arg grabber here.
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
extern "C" char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
  if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
    *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
    return _swift_stdlib_ProcessOverrideUnsafeArgv;
  }

  swift::fatalError(0,
      "fatal error: Command line arguments not supported on this platform.\n");
}
#endif

<|endoftext|>


<commit_before>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "FireSimulator.h"
#include "../World.h"
#include "../BlockID.h"
#include "../Defines.h"
#include "../Chunk.h"

// Easy switch for turning on debugging logging:
#if 0
	#define FLOG LOGD
#else
	#define FLOG(...)
#endif

#define MAX_CHANCE_REPLACE_FUEL 100000
#define MAX_CHANCE_FLAMMABILITY 100000

static const struct
{
	int x, y, z;
} gCrossCoords[] =
{
	{ 1, 0,  0},
	{-1, 0,  0},
	{ 0, 0,  1},
	{ 0, 0, -1},
} ;

static const struct
{
	int x, y, z;
} gNeighborCoords[] =
{
	{ 1,  0,  0},
	{-1,  0,  0},
	{ 0,  1,  0},
	{ 0, -1,  0},
	{ 0,  0,  1},
	{ 0,  0, -1},
} ;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cFireSimulator:

cFireSimulator::cFireSimulator(cWorld & a_World, cIniFile & a_IniFile) :
	cSimulator(a_World)
{
	// Read params from the ini file:
	m_BurnStepTimeFuel    = a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeFuel",     500);
	m_BurnStepTimeNonfuel = a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeNonfuel",  100);
	m_Flammability        = a_IniFile.GetValueSetI("FireSimulator", "Flammability",          50);
	m_ReplaceFuelChance   = a_IniFile.GetValueSetI("FireSimulator", "ReplaceFuelChance",  50000);
}

cFireSimulator::~cFireSimulator()
{
}

void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
	cCoordWithIntList & Data = a_Chunk->GetFireSimulatorData();

	int NumMSecs = (int)a_Dt;
	for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
	{
		int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z);
		BLOCKTYPE BlockType = a_Chunk->GetBlock(idx);

		if (!IsAllowedBlock(BlockType))
		{
			// The block is no longer eligible (not a fire block anymore; a player probably placed a block over the fire)
			FLOG("FS: Removing block {%d, %d, %d}",
				itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
			);
			itr = Data.erase(itr);
			continue;
		}

		// Try to spread the fire:
		TrySpreadFire(a_Chunk, itr->x, itr->y, itr->z);

		itr->Data -= NumMSecs;
		if (itr->Data >= 0)
		{
			// Not yet, wait for it longer
			++itr;
			continue;
		}

		// Burn out the fire one step by increasing the meta:
		/*
		FLOG("FS: Fire at {%d, %d, %d} is stepping",
			itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
		);
		*/
		NIBBLETYPE BlockMeta = a_Chunk->GetMeta(idx);
		if (BlockMeta == 0x0f)
		{
			// The fire burnt out completely
			FLOG("FS: Fire at {%d, %d, %d} burnt out, removing the fire block",
				itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
			);
			a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
			RemoveFuelNeighbors(a_Chunk, itr->x, itr->y, itr->z);
			itr = Data.erase(itr);
			continue;
		}

		if((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z))))
		{
			a_Chunk->SetMeta(idx, BlockMeta + 1);
		}
		itr->Data = GetBurnStepTime(a_Chunk, itr->x, itr->y, itr->z);  // TODO: Add some randomness into this
	}  // for itr - Data[]
}

bool cFireSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
{
	return (a_BlockType == E_BLOCK_FIRE);
}

bool cFireSimulator::IsFuel(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_PLANKS:
		case E_BLOCK_LEAVES:
		case E_BLOCK_LOG:
		case E_BLOCK_WOOL:
		case E_BLOCK_BOOKCASE:
		case E_BLOCK_FENCE:
		case E_BLOCK_TNT:
		case E_BLOCK_VINES:
		{
			return true;
		}
	}
	return false;
}

bool cFireSimulator::DoesBurnForever(BLOCKTYPE a_BlockType)
{
	return (a_BlockType == E_BLOCK_NETHERRACK);
}

void cFireSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
	if ((a_Chunk == NULL) || !a_Chunk->IsValid())
	{
		return;
	}

	int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
	int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
	BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_BlockY, RelZ);
	if (!IsAllowedBlock(BlockType))
	{
		return;
	}

	// Check for duplicates:
	cFireSimulatorChunkData & ChunkData = a_Chunk->GetFireSimulatorData();
	for (cCoordWithIntList::iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr)
	{
		if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
		{
			// Already present, skip adding
			return;
		}
	}  // for itr - ChunkData[]

	FLOG("FS: Adding block {%d, %d, %d}", a_BlockX, a_BlockY, a_BlockZ);
	ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ, 100));
}

int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	bool IsBlockBelowSolid = false;
	if (a_RelY > 0)
	{
		BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ);
		if (DoesBurnForever(BlockBelow))
		{
			// Is burning atop of netherrack, burn forever (re-check in 10 sec)
			return 10000;
		}
		if (IsFuel(BlockBelow))
		{
			return m_BurnStepTimeFuel;
		}
		IsBlockBelowSolid = g_BlockIsSolid[BlockBelow];
	}

	for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
	{
		BLOCKTYPE  BlockType;
		NIBBLETYPE BlockMeta;
		if (a_Chunk->UnboundedRelGetBlock(a_RelX + gCrossCoords[i].x, a_RelY, a_RelZ + gCrossCoords[i].z, BlockType, BlockMeta))
		{
			if (IsFuel(BlockType))
			{
				return m_BurnStepTimeFuel;
			}
		}
	}  // for i - gCrossCoords[]

	if (!IsBlockBelowSolid && (a_RelY >= 0))
	{
		// Checked through everything, nothing was flammable
		// If block below isn't solid, we can't have fire, it would be a non-fueled fire
		// SetBlock just to make sure fire doesn't spawn
		a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
		return 0;
	}
	return m_BurnStepTimeNonfuel;
}

void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	/*
	if (m_World.GetTickRandomNumber(10000) > 100)
	{
		// Make the chance to spread 100x smaller
		return;
	}
	*/

	for (int x = a_RelX - 1; x <= a_RelX + 1; x++)
	{
		for (int z = a_RelZ - 1; z <= a_RelZ + 1; z++)
		{
			for (int y = a_RelY - 1; y <= a_RelY + 2; y++)  // flames spread up one more block than around
			{
				// No need to check the coords for equality with the parent block,
				// it cannot catch fire anyway (because it's not an air block)

				if (m_World.GetTickRandomNumber(MAX_CHANCE_FLAMMABILITY) > m_Flammability)
				{
					continue;
				}

				// Start the fire in the neighbor {x, y, z}
				/*
				FLOG("FS: Trying to start fire at {%d, %d, %d}.",
					x + a_Chunk->GetPosX() * cChunkDef::Width, y, z + a_Chunk->GetPosZ() * cChunkDef::Width
				);
				*/
				if (CanStartFireInBlock(a_Chunk, x, y, z))
				{
					FLOG("FS: Starting new fire at {%d, %d, %d}.",
						x + a_Chunk->GetPosX() * cChunkDef::Width, y, z + a_Chunk->GetPosZ() * cChunkDef::Width
					);
					a_Chunk->UnboundedRelSetBlock(x, y, z, E_BLOCK_FIRE, 0);
				}
			}  // for y
		}  // for z
	}  // for x
}

void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++)
	{
		BLOCKTYPE  BlockType;
		NIBBLETYPE BlockMeta;
		if (!a_Chunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta))
		{
			// Neighbor not accessible, ignore it
			continue;
		}
		if (!IsFuel(BlockType))
		{
			continue;
		}
		bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance);
		a_Chunk->UnboundedRelSetBlock(
			a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z,
			ShouldReplaceFuel ? E_BLOCK_FIRE : E_BLOCK_AIR, 0
		);
	}  // for i - Coords[]
}

bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ)
{
	BLOCKTYPE  BlockType;
	NIBBLETYPE BlockMeta;
	if (!a_NearChunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
	{
		// The chunk is not accessible
		return false;
	}

	if (BlockType != E_BLOCK_AIR)
	{
		// Only an air block can be replaced by a fire block
		return false;
	}

	for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++)
	{
		if (!a_NearChunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta))
		{
			// Neighbor inaccessible, skip it while evaluating
			continue;
		}
		if (IsFuel(BlockType))
		{
			return true;
		}
	}  // for i - Coords[]
	return false;
}

<commit_msg>Add Hay Bale to Burnable<commit_after>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "FireSimulator.h"
#include "../World.h"
#include "../BlockID.h"
#include "../Defines.h"
#include "../Chunk.h"

// Easy switch for turning on debugging logging:
#if 0
	#define FLOG LOGD
#else
	#define FLOG(...)
#endif

#define MAX_CHANCE_REPLACE_FUEL 100000
#define MAX_CHANCE_FLAMMABILITY 100000

static const struct
{
	int x, y, z;
} gCrossCoords[] =
{
	{ 1, 0,  0},
	{-1, 0,  0},
	{ 0, 0,  1},
	{ 0, 0, -1},
} ;

static const struct
{
	int x, y, z;
} gNeighborCoords[] =
{
	{ 1,  0,  0},
	{-1,  0,  0},
	{ 0,  1,  0},
	{ 0, -1,  0},
	{ 0,  0,  1},
	{ 0,  0, -1},
} ;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cFireSimulator:

cFireSimulator::cFireSimulator(cWorld & a_World, cIniFile & a_IniFile) :
	cSimulator(a_World)
{
	// Read params from the ini file:
	m_BurnStepTimeFuel    = a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeFuel",     500);
	m_BurnStepTimeNonfuel = a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeNonfuel",  100);
	m_Flammability        = a_IniFile.GetValueSetI("FireSimulator", "Flammability",          50);
	m_ReplaceFuelChance   = a_IniFile.GetValueSetI("FireSimulator", "ReplaceFuelChance",  50000);
}

cFireSimulator::~cFireSimulator()
{
}

void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
	cCoordWithIntList & Data = a_Chunk->GetFireSimulatorData();

	int NumMSecs = (int)a_Dt;
	for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
	{
		int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z);
		BLOCKTYPE BlockType = a_Chunk->GetBlock(idx);

		if (!IsAllowedBlock(BlockType))
		{
			// The block is no longer eligible (not a fire block anymore; a player probably placed a block over the fire)
			FLOG("FS: Removing block {%d, %d, %d}",
				itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
			);
			itr = Data.erase(itr);
			continue;
		}

		// Try to spread the fire:
		TrySpreadFire(a_Chunk, itr->x, itr->y, itr->z);

		itr->Data -= NumMSecs;
		if (itr->Data >= 0)
		{
			// Not yet, wait for it longer
			++itr;
			continue;
		}

		// Burn out the fire one step by increasing the meta:
		/*
		FLOG("FS: Fire at {%d, %d, %d} is stepping",
			itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
		);
		*/
		NIBBLETYPE BlockMeta = a_Chunk->GetMeta(idx);
		if (BlockMeta == 0x0f)
		{
			// The fire burnt out completely
			FLOG("FS: Fire at {%d, %d, %d} burnt out, removing the fire block",
				itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
			);
			a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
			RemoveFuelNeighbors(a_Chunk, itr->x, itr->y, itr->z);
			itr = Data.erase(itr);
			continue;
		}

		if((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z))))
		{
			a_Chunk->SetMeta(idx, BlockMeta + 1);
		}
		itr->Data = GetBurnStepTime(a_Chunk, itr->x, itr->y, itr->z);  // TODO: Add some randomness into this
	}  // for itr - Data[]
}

bool cFireSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
{
	return (a_BlockType == E_BLOCK_FIRE);
}

bool cFireSimulator::IsFuel(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_PLANKS:
		case E_BLOCK_LEAVES:
		case E_BLOCK_LOG:
		case E_BLOCK_WOOL:
		case E_BLOCK_BOOKCASE:
		case E_BLOCK_FENCE:
		case E_BLOCK_TNT:
		case E_BLOCK_VINES:
		case E_BLOCK_HAY_BALE:
		{
			return true;
		}
	}
	return false;
}

bool cFireSimulator::DoesBurnForever(BLOCKTYPE a_BlockType)
{
	return (a_BlockType == E_BLOCK_NETHERRACK);
}

void cFireSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
	if ((a_Chunk == NULL) || !a_Chunk->IsValid())
	{
		return;
	}

	int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
	int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
	BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_BlockY, RelZ);
	if (!IsAllowedBlock(BlockType))
	{
		return;
	}

	// Check for duplicates:
	cFireSimulatorChunkData & ChunkData = a_Chunk->GetFireSimulatorData();
	for (cCoordWithIntList::iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr)
	{
		if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
		{
			// Already present, skip adding
			return;
		}
	}  // for itr - ChunkData[]

	FLOG("FS: Adding block {%d, %d, %d}", a_BlockX, a_BlockY, a_BlockZ);
	ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ, 100));
}

int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	bool IsBlockBelowSolid = false;
	if (a_RelY > 0)
	{
		BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ);
		if (DoesBurnForever(BlockBelow))
		{
			// Is burning atop of netherrack, burn forever (re-check in 10 sec)
			return 10000;
		}
		if (IsFuel(BlockBelow))
		{
			return m_BurnStepTimeFuel;
		}
		IsBlockBelowSolid = g_BlockIsSolid[BlockBelow];
	}

	for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
	{
		BLOCKTYPE  BlockType;
		NIBBLETYPE BlockMeta;
		if (a_Chunk->UnboundedRelGetBlock(a_RelX + gCrossCoords[i].x, a_RelY, a_RelZ + gCrossCoords[i].z, BlockType, BlockMeta))
		{
			if (IsFuel(BlockType))
			{
				return m_BurnStepTimeFuel;
			}
		}
	}  // for i - gCrossCoords[]

	if (!IsBlockBelowSolid && (a_RelY >= 0))
	{
		// Checked through everything, nothing was flammable
		// If block below isn't solid, we can't have fire, it would be a non-fueled fire
		// SetBlock just to make sure fire doesn't spawn
		a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
		return 0;
	}
	return m_BurnStepTimeNonfuel;
}

void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	/*
	if (m_World.GetTickRandomNumber(10000) > 100)
	{
		// Make the chance to spread 100x smaller
		return;
	}
	*/

	for (int x = a_RelX - 1; x <= a_RelX + 1; x++)
	{
		for (int z = a_RelZ - 1; z <= a_RelZ + 1; z++)
		{
			for (int y = a_RelY - 1; y <= a_RelY + 2; y++)  // flames spread up one more block than around
			{
				// No need to check the coords for equality with the parent block,
				// it cannot catch fire anyway (because it's not an air block)

				if (m_World.GetTickRandomNumber(MAX_CHANCE_FLAMMABILITY) > m_Flammability)
				{
					continue;
				}

				// Start the fire in the neighbor {x, y, z}
				/*
				FLOG("FS: Trying to start fire at {%d, %d, %d}.",
					x + a_Chunk->GetPosX() * cChunkDef::Width, y, z + a_Chunk->GetPosZ() * cChunkDef::Width
				);
				*/
				if (CanStartFireInBlock(a_Chunk, x, y, z))
				{
					FLOG("FS: Starting new fire at {%d, %d, %d}.",
						x + a_Chunk->GetPosX() * cChunkDef::Width, y, z + a_Chunk->GetPosZ() * cChunkDef::Width
					);
					a_Chunk->UnboundedRelSetBlock(x, y, z, E_BLOCK_FIRE, 0);
				}
			}  // for y
		}  // for z
	}  // for x
}

void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++)
	{
		BLOCKTYPE  BlockType;
		NIBBLETYPE BlockMeta;
		if (!a_Chunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta))
		{
			// Neighbor not accessible, ignore it
			continue;
		}
		if (!IsFuel(BlockType))
		{
			continue;
		}
		bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance);
		a_Chunk->UnboundedRelSetBlock(
			a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z,
			ShouldReplaceFuel ? E_BLOCK_FIRE : E_BLOCK_AIR, 0
		);
	}  // for i - Coords[]
}

bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ)
{
	BLOCKTYPE  BlockType;
	NIBBLETYPE BlockMeta;
	if (!a_NearChunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
	{
		// The chunk is not accessible
		return false;
	}

	if (BlockType != E_BLOCK_AIR)
	{
		// Only an air block can be replaced by a fire block
		return false;
	}

	for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++)
	{
		if (!a_NearChunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta))
		{
			// Neighbor inaccessible, skip it while evaluating
			continue;
		}
		if (IsFuel(BlockType))
		{
			return true;
		}
	}  // for i - Coords[]
	return false;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "config_profile/profile.h"
#include "media_manager/media_manager_impl.h"
#include "media_manager/audio/from_mic_recorder_listener.h"
#include "media_manager/streamer_listener.h"
#include "application_manager/message_helper.h"
#include "application_manager/application.h"
#include "application_manager/application_manager_impl.h"
#include "application_manager/application_impl.h"
#include "utils/file_system.h"
#include "utils/logger.h"
#if defined(EXTENDED_MEDIA_MODE)
#include "media_manager/audio/a2dp_source_player_adapter.h"
#include "media_manager/audio/from_mic_recorder_adapter.h"
#endif
#include "media_manager/video/socket_video_streamer_adapter.h"
#include "media_manager/audio/socket_audio_streamer_adapter.h"
#include "media_manager/video/pipe_video_streamer_adapter.h"
#include "media_manager/audio/pipe_audio_streamer_adapter.h"
#include "media_manager/video/video_stream_to_file_adapter.h"

namespace media_manager {

using profile::Profile;

CREATE_LOGGERPTR_GLOBAL(logger_, "MediaManagerImpl")

MediaManagerImpl::MediaManagerImpl()
  : protocol_handler_(NULL)
  , a2dp_player_(NULL)
  , from_mic_recorder_(NULL)
  , video_streamer_(NULL)
  , audio_streamer_(NULL)
  , video_stream_active_(false)
  , audio_stream_active_(false)
  , streaming_timer_("Streaming timer", this, &MediaManagerImpl::OnStreamingEnded)
  , streaming_app_id_(0) {
  Init();
}

MediaManagerImpl::~MediaManagerImpl() {
  if (a2dp_player_) {
    delete a2dp_player_;
    a2dp_player_ = NULL;
  }

  if (from_mic_recorder_) {
    delete from_mic_recorder_;
    from_mic_recorder_ = NULL;
  }

  if (video_streamer_) {
    delete video_streamer_;
    video_streamer_ = NULL;
  }

  if (audio_streamer_) {
    delete audio_streamer_;
    audio_streamer_ = NULL;
  }
}

void MediaManagerImpl::SetProtocolHandler(
  protocol_handler::ProtocolHandler* protocol_handler) {
  protocol_handler_ = protocol_handler;
}

void MediaManagerImpl::Init() {
  LOG4CXX_INFO(logger_, "MediaManagerImpl::Init()");

#if defined(EXTENDED_MEDIA_MODE)
  LOG4CXX_INFO(logger_, "Called Init with default configuration.");
  a2dp_player_ = new A2DPSourcePlayerAdapter();
  from_mic_recorder_ = new FromMicRecorderAdapter();
#endif

  if ("socket" == profile::Profile::instance()->video_server_type()) {
    video_streamer_ = new SocketVideoStreamerAdapter();
  } else if ("pipe" == profile::Profile::instance()->video_server_type()) {
    video_streamer_ = new PipeVideoStreamerAdapter();
  } else if ("file" == profile::Profile::instance()->video_server_type()) {
    video_streamer_ = new VideoStreamToFileAdapter(
        profile::Profile::instance()->video_stream_file());
  }

  if ("socket" == profile::Profile::instance()->audio_server_type()) {
    audio_streamer_ = new SocketAudioStreamerAdapter();
  } else if ("pipe" == profile::Profile::instance()->audio_server_type()) {
    audio_streamer_ = new PipeAudioStreamerAdapter();
  } else if ("file" == profile::Profile::instance()->audio_server_type()) {
    audio_streamer_ = new VideoStreamToFileAdapter(
        profile::Profile::instance()->audio_stream_file());
  }

  stop_streaming_timeout_ = profile::Profile::instance()->stop_streaming_timeout();

  video_streamer_listener_ = new StreamerListener();
  audio_streamer_listener_ = new StreamerListener();

  if (NULL != video_streamer_) {
    video_streamer_->AddListener(video_streamer_listener_);
  }

  if (NULL != audio_streamer_) {
    audio_streamer_->AddListener(audio_streamer_listener_);
  }
}

void MediaManagerImpl::OnStreamingEnded() {
  application_manager::ApplicationManagerImpl::instance()->StreamingEnded(streaming_app_id_);
}

void MediaManagerImpl::PlayA2DPSource(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (a2dp_player_) {
    a2dp_player_->StartActivity(application_key);
  }
}

void MediaManagerImpl::StopA2DPSource(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (a2dp_player_) {
    a2dp_player_->StopActivity(application_key);
  }
}

void MediaManagerImpl::StartMicrophoneRecording(
  int32_t application_key,
  const std::string& output_file,
  int32_t duration) {
  LOG4CXX_INFO(logger_, "MediaManagerImpl::StartMicrophoneRecording to "
               << output_file);
  application_manager::ApplicationSharedPtr app =
    application_manager::ApplicationManagerImpl::instance()->
      application(application_key);
  std::string file_path =
  profile::Profile::instance()->app_storage_folder();
  file_path += "/";
  file_path += output_file;
  from_mic_listener_ = new FromMicRecorderListener(file_path);
#if defined(EXTENDED_MEDIA_MODE)
  if (from_mic_recorder_) {
    from_mic_recorder_->AddListener(from_mic_listener_);
    (static_cast<FromMicRecorderAdapter*>(from_mic_recorder_))
    ->set_output_file(file_path);
    (static_cast<FromMicRecorderAdapter*>(from_mic_recorder_))
    ->set_duration(duration);
    from_mic_recorder_->StartActivity(application_key);
  }
#else
  if (file_system::FileExists(file_path)) {
    LOG4CXX_INFO(logger_, "File " << output_file << " exists, removing");
    if (file_system::DeleteFile(file_path)) {
      LOG4CXX_INFO(logger_, "File " << output_file << " removed");
    }
    else {
      LOG4CXX_WARN(logger_, "Could not remove file " << output_file);
    }
  }
  const std::string record_file_source =
      profile::Profile::instance()->app_resourse_folder() + "/" +
      profile::Profile::instance()->recording_file_source();
  std::vector<uint8_t> buf;
  if (file_system::ReadBinaryFile(record_file_source, buf)) {
    if (file_system::Write(file_path, buf)) {
      LOG4CXX_INFO(logger_,
        "File " << record_file_source << " copied to " << output_file);
    }
    else {
      LOG4CXX_WARN(logger_, "Could not write to file " << output_file);
    }
  }
  else {
    LOG4CXX_WARN(logger_, "Could not read file " << record_file_source);
  }
#endif
  from_mic_listener_->OnActivityStarted(application_key);
}

void MediaManagerImpl::StopMicrophoneRecording(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
#if defined(EXTENDED_MEDIA_MODE)
  if (from_mic_recorder_) {
    from_mic_recorder_->StopActivity(application_key);
  }
#endif
  if (from_mic_listener_) {
    from_mic_listener_->OnActivityEnded(application_key);
  }
}

void MediaManagerImpl::StartVideoStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (video_streamer_) {
    if (!video_stream_active_) {
      video_stream_active_ = true;
      video_streamer_->StartActivity(application_key);
      application_manager::MessageHelper::SendNaviStartStream(application_key);
    }
  }
}

void MediaManagerImpl::StopVideoStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (video_streamer_) {
    video_stream_active_ = false;
    application_manager::MessageHelper::SendNaviStopStream(application_key);
    video_streamer_->StopActivity(application_key);
  }
}

void MediaManagerImpl::StartAudioStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (audio_streamer_) {
    if (!audio_stream_active_) {
      audio_stream_active_ = true;
      audio_streamer_->StartActivity(application_key);
      application_manager::MessageHelper::SendAudioStartStream(application_key);
    }
  }
}

void MediaManagerImpl::StopAudioStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (audio_streamer_) {
    audio_stream_active_ = false;
    application_manager::MessageHelper::SendAudioStopStream(application_key);
    audio_streamer_->StopActivity(application_key);
  }
}

void MediaManagerImpl::OnMessageReceived(
    const ::protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);

  using namespace application_manager;
  using namespace protocol_handler;

  streaming_app_id_ = message->connection_key();
  ServiceType streaming_app_service_type = message->service_type();

  MediaAdapterImpl* streamer = 0;
  if (streaming_app_service_type == kMobileNav) {
    if ((ApplicationManagerImpl::instance()-> IsVideoStreamingAllowed(streaming_app_id_))) {
      streamer = video_streamer_;
    }
  } else if (streaming_app_service_type == kAudio) {
    if ((ApplicationManagerImpl::instance()-> IsAudioStreamingAllowed(streaming_app_id_))) {
      streamer = audio_streamer_;
    }
  }

  if (streamer) {
    if (ApplicationManagerImpl::instance()->CanAppStream(streaming_app_id_)) {
      streamer->SendData(streaming_app_id_, message);
      streaming_timer_.start(stop_streaming_timeout_);
    } else {
      ApplicationManagerImpl::instance()->ForbidStreaming(streaming_app_id_);
      LOG4CXX_DEBUG(logger_, "The application trying to stream when it should not.");
    }
  }
}

void MediaManagerImpl::OnMobileMessageSent(
  const ::protocol_handler::RawMessagePtr message) {
}

void MediaManagerImpl::FramesProcessed(int32_t application_key,
                                       int32_t frame_number) {
  if (protocol_handler_) {
    protocol_handler_->SendFramesNumber(application_key,
                                        frame_number);
  }
}

}  //  namespace media_manager
<commit_msg>Post review changes.<commit_after>/*
 * Copyright (c) 2014, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "config_profile/profile.h"
#include "media_manager/media_manager_impl.h"
#include "media_manager/audio/from_mic_recorder_listener.h"
#include "media_manager/streamer_listener.h"
#include "application_manager/message_helper.h"
#include "application_manager/application.h"
#include "application_manager/application_manager_impl.h"
#include "application_manager/application_impl.h"
#include "utils/file_system.h"
#include "utils/logger.h"
#if defined(EXTENDED_MEDIA_MODE)
#include "media_manager/audio/a2dp_source_player_adapter.h"
#include "media_manager/audio/from_mic_recorder_adapter.h"
#endif
#include "media_manager/video/socket_video_streamer_adapter.h"
#include "media_manager/audio/socket_audio_streamer_adapter.h"
#include "media_manager/video/pipe_video_streamer_adapter.h"
#include "media_manager/audio/pipe_audio_streamer_adapter.h"
#include "media_manager/video/video_stream_to_file_adapter.h"

namespace media_manager {

using profile::Profile;

CREATE_LOGGERPTR_GLOBAL(logger_, "MediaManagerImpl")

MediaManagerImpl::MediaManagerImpl()
  : protocol_handler_(NULL)
  , a2dp_player_(NULL)
  , from_mic_recorder_(NULL)
  , video_streamer_(NULL)
  , audio_streamer_(NULL)
  , video_stream_active_(false)
  , audio_stream_active_(false)
  , streaming_timer_("Streaming timer", this, &MediaManagerImpl::OnStreamingEnded)
  , streaming_app_id_(0) {
  Init();
}

MediaManagerImpl::~MediaManagerImpl() {
  if (a2dp_player_) {
    delete a2dp_player_;
    a2dp_player_ = NULL;
  }

  if (from_mic_recorder_) {
    delete from_mic_recorder_;
    from_mic_recorder_ = NULL;
  }

  if (video_streamer_) {
    delete video_streamer_;
    video_streamer_ = NULL;
  }

  if (audio_streamer_) {
    delete audio_streamer_;
    audio_streamer_ = NULL;
  }
}

void MediaManagerImpl::SetProtocolHandler(
  protocol_handler::ProtocolHandler* protocol_handler) {
  protocol_handler_ = protocol_handler;
}

void MediaManagerImpl::Init() {
  LOG4CXX_INFO(logger_, "MediaManagerImpl::Init()");

#if defined(EXTENDED_MEDIA_MODE)
  LOG4CXX_INFO(logger_, "Called Init with default configuration.");
  a2dp_player_ = new A2DPSourcePlayerAdapter();
  from_mic_recorder_ = new FromMicRecorderAdapter();
#endif

  if ("socket" == profile::Profile::instance()->video_server_type()) {
    video_streamer_ = new SocketVideoStreamerAdapter();
  } else if ("pipe" == profile::Profile::instance()->video_server_type()) {
    video_streamer_ = new PipeVideoStreamerAdapter();
  } else if ("file" == profile::Profile::instance()->video_server_type()) {
    video_streamer_ = new VideoStreamToFileAdapter(
        profile::Profile::instance()->video_stream_file());
  }

  if ("socket" == profile::Profile::instance()->audio_server_type()) {
    audio_streamer_ = new SocketAudioStreamerAdapter();
  } else if ("pipe" == profile::Profile::instance()->audio_server_type()) {
    audio_streamer_ = new PipeAudioStreamerAdapter();
  } else if ("file" == profile::Profile::instance()->audio_server_type()) {
    audio_streamer_ = new VideoStreamToFileAdapter(
        profile::Profile::instance()->audio_stream_file());
  }

  stop_streaming_timeout_ = profile::Profile::instance()->stop_streaming_timeout();

  video_streamer_listener_ = new StreamerListener();
  audio_streamer_listener_ = new StreamerListener();

  if (NULL != video_streamer_) {
    video_streamer_->AddListener(video_streamer_listener_);
  }

  if (NULL != audio_streamer_) {
    audio_streamer_->AddListener(audio_streamer_listener_);
  }
}

void MediaManagerImpl::OnStreamingEnded() {
  application_manager::ApplicationManagerImpl::instance()->StreamingEnded(streaming_app_id_);
}

void MediaManagerImpl::PlayA2DPSource(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (a2dp_player_) {
    a2dp_player_->StartActivity(application_key);
  }
}

void MediaManagerImpl::StopA2DPSource(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (a2dp_player_) {
    a2dp_player_->StopActivity(application_key);
  }
}

void MediaManagerImpl::StartMicrophoneRecording(
  int32_t application_key,
  const std::string& output_file,
  int32_t duration) {
  LOG4CXX_INFO(logger_, "MediaManagerImpl::StartMicrophoneRecording to "
               << output_file);
  application_manager::ApplicationSharedPtr app =
    application_manager::ApplicationManagerImpl::instance()->
      application(application_key);
  std::string file_path =
  profile::Profile::instance()->app_storage_folder();
  file_path += "/";
  file_path += output_file;
  from_mic_listener_ = new FromMicRecorderListener(file_path);
#if defined(EXTENDED_MEDIA_MODE)
  if (from_mic_recorder_) {
    from_mic_recorder_->AddListener(from_mic_listener_);
    (static_cast<FromMicRecorderAdapter*>(from_mic_recorder_))
    ->set_output_file(file_path);
    (static_cast<FromMicRecorderAdapter*>(from_mic_recorder_))
    ->set_duration(duration);
    from_mic_recorder_->StartActivity(application_key);
  }
#else
  if (file_system::FileExists(file_path)) {
    LOG4CXX_INFO(logger_, "File " << output_file << " exists, removing");
    if (file_system::DeleteFile(file_path)) {
      LOG4CXX_INFO(logger_, "File " << output_file << " removed");
    }
    else {
      LOG4CXX_WARN(logger_, "Could not remove file " << output_file);
    }
  }
  const std::string record_file_source =
      profile::Profile::instance()->app_resourse_folder() + "/" +
      profile::Profile::instance()->recording_file_source();
  std::vector<uint8_t> buf;
  if (file_system::ReadBinaryFile(record_file_source, buf)) {
    if (file_system::Write(file_path, buf)) {
      LOG4CXX_INFO(logger_,
        "File " << record_file_source << " copied to " << output_file);
    }
    else {
      LOG4CXX_WARN(logger_, "Could not write to file " << output_file);
    }
  }
  else {
    LOG4CXX_WARN(logger_, "Could not read file " << record_file_source);
  }
#endif
  from_mic_listener_->OnActivityStarted(application_key);
}

void MediaManagerImpl::StopMicrophoneRecording(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
#if defined(EXTENDED_MEDIA_MODE)
  if (from_mic_recorder_) {
    from_mic_recorder_->StopActivity(application_key);
  }
#endif
  if (from_mic_listener_) {
    from_mic_listener_->OnActivityEnded(application_key);
  }
}

void MediaManagerImpl::StartVideoStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (video_streamer_) {
    if (!video_stream_active_) {
      video_stream_active_ = true;
      video_streamer_->StartActivity(application_key);
      application_manager::MessageHelper::SendNaviStartStream(application_key);
    }
  }
}

void MediaManagerImpl::StopVideoStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (video_streamer_) {
    video_stream_active_ = false;
    application_manager::MessageHelper::SendNaviStopStream(application_key);
    video_streamer_->StopActivity(application_key);
  }
}

void MediaManagerImpl::StartAudioStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);

  if (audio_streamer_) {
    if (!audio_stream_active_) {
      audio_stream_active_ = true;
      audio_streamer_->StartActivity(application_key);
      application_manager::MessageHelper::SendAudioStartStream(application_key);
    }
  }
}

void MediaManagerImpl::StopAudioStreaming(int32_t application_key) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (audio_streamer_) {
    audio_stream_active_ = false;
    application_manager::MessageHelper::SendAudioStopStream(application_key);
    audio_streamer_->StopActivity(application_key);
  }
}

void MediaManagerImpl::OnMessageReceived(
    const ::protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);

  using namespace application_manager;
  using namespace protocol_handler;

  streaming_app_id_ = message->connection_key();
  ServiceType streaming_app_service_type = message->service_type();

  MediaAdapterImpl* streamer = NULL;
  if (streaming_app_service_type == kMobileNav) {
    if ((ApplicationManagerImpl::instance()-> IsVideoStreamingAllowed(streaming_app_id_))) {
      streamer = video_streamer_;
    }
  } else if (streaming_app_service_type == kAudio) {
    if ((ApplicationManagerImpl::instance()-> IsAudioStreamingAllowed(streaming_app_id_))) {
      streamer = audio_streamer_;
    }
  }

  if (streamer) {
    if (ApplicationManagerImpl::instance()->CanAppStream(streaming_app_id_)) {
      streamer->SendData(streaming_app_id_, message);
      streaming_timer_.start(stop_streaming_timeout_);
    } else {
      ApplicationManagerImpl::instance()->ForbidStreaming(streaming_app_id_);
      LOG4CXX_ERROR(logger_, "The application trying to stream when it should not.");
    }
  }
}

void MediaManagerImpl::OnMobileMessageSent(
  const ::protocol_handler::RawMessagePtr message) {
}

void MediaManagerImpl::FramesProcessed(int32_t application_key,
                                       int32_t frame_number) {
  if (protocol_handler_) {
    protocol_handler_->SendFramesNumber(application_key,
                                        frame_number);
  }
}

}  //  namespace media_manager
<|endoftext|>


<commit_before>#include <Socket/SocketSerialized.hpp>
#include <Socket/define.hpp>

#include <thread>

namespace ntw {

SocketSerialized::SocketSerialized(Socket::Dommaine dommaine,Socket::Type type,int protocole): Serializer(255), Socket(dommaine,type,protocole), status(0)
{
    //reserver les 2 premier bits pour la taille
    _cursor_end =_cursor_begin = 4;
    //is_send=false;
};

SocketSerialized::SocketSerialized(Socket&& s) : Serializer(255)
{
    std::swap(s.sock,sock);
    std::swap(s.sock_cfg,sock_cfg);
    _cursor_end =_cursor_begin = 4;
};

int SocketSerialized::send()
{
    //écrire la taille dans les 2 premier oct
    uint16_t size = _cursor_end - _cursor_begin;
    uint8_t *d = (uint8_t *)&size;
    #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    _buffer[_cursor_begin - 4] = d[0];
    _buffer[_cursor_begin - 3] = d[1];
    #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    _buffer[_cursor_begin - 4] = d[1];
    _buffer[_cursor_begin - 3] = d[0];
    #else
    #error "byte orden not suported (PDP endian)"
    #endif

    {
        uint16_t st = status;
        d = (uint8_t*)&st;
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        _buffer[_cursor_begin - 2] = d[0];
        _buffer[_cursor_begin - 1] = d[1];
        #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
        _buffer[_cursor_begin - 2] = d[1];
        _buffer[_cursor_begin - 1] = d[0];
        #else
        #error "byte orden not suported (PDP endian)"
        #endif
    }
    //envoyer
    int res = Socket::send(_buffer+_cursor_begin-4, 4+size);
    //reset
    //clear();
    return res;
};

int SocketSerialized::receive()
{
    //recuperer la taille dans les 4 premier oct
    int res = Socket::receive(_buffer,4);
    if (res > 0)
    {
        uint8_t d[2];
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        d[0]= _buffer[0];
        d[1]= _buffer[1];
        #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
        d[1]= _buffer[0];
        d[0]= _buffer[1];
        #else
        #error "byte orden not suported (PDP endian)"
        #endif
        uint16_t size = *(uint16_t*)&d;

        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        d[0]= _buffer[2];
        d[1]= _buffer[3];
        #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
        d[1]= _buffer[2];
        d[0]= _buffer[3];
        #else
        #error "byte orden not suported (PDP endian)"
        #endif
        status = *(uint16_t*)&d;

        //reset
        if (int(_buffer_size) < 4+size)
            resize(4+size);
        //else _buffer_size ne change pas
        _cursor_begin = 4;
        _cursor_end = 4+size;
        //remplacer le buffer
        if(size>0)
        {
            int recv_left = size;
            int recv = 0;
            while(recv_left > 0)
            {
                recv = Socket::receive(_buffer+res,recv_left);
                if(recv<=0)
                    //TODO ERROR
                    break;
                res+=recv;
                recv_left -=recv;
            }
        }
    }
    else
    {
        clear();
        setStatus(NTW_STOP_CONNEXION);
    }
    return res;
};

void SocketSerialized::setStatus(short int st)
{
    status = st;
}

short int SocketSerialized::getStatus()const
{
    return status;
}

void SocketSerialized::clear()
{
    _cursor_begin = _cursor_end = 4;
}

std::ostream& operator<<(std::ostream& output,const SocketSerialized& self)
{
    output<<"[id("<<self.id()<<"),size("<<self.size()<<"),status("<<self.status<<")]";
    for(unsigned int i=self._cursor_begin; i<self._cursor_end;++i)
    {
        if(self._buffer[i] < 33 or self._buffer[i] >126)
            output<<"<"<<(int)self._buffer[i]<<">";
        else
            output<<"'"<<(char)self._buffer[i]<<"'";
    }
    return output;
};

};
<commit_msg>change header size for bigger socket<commit_after>#include <Socket/SocketSerialized.hpp>
#include <Socket/define.hpp>

#include <thread>

namespace ntw {

#define HEADER_SIZE (4+2)

SocketSerialized::SocketSerialized(Socket::Dommaine dommaine,Socket::Type type,int protocole): Serializer(255), Socket(dommaine,type,protocole), status(0)
{
    //reserver les 2 premier bits pour la taille
    _cursor_end =_cursor_begin = HEADER_SIZE;
    //is_send=false;
};

SocketSerialized::SocketSerialized(Socket&& s) : Serializer(255)
{
    std::swap(s.sock,sock);
    std::swap(s.sock_cfg,sock_cfg);
    _cursor_end =_cursor_begin = HEADER_SIZE;
};

int SocketSerialized::send()
{
    //écrire la taille dans les 2 premier oct
    uint32_t size = _cursor_end - _cursor_begin;
    uint8_t *d = (uint8_t *)&size;
    #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    _buffer[_cursor_begin - 6] = d[0];
    _buffer[_cursor_begin - 5] = d[1];
    _buffer[_cursor_begin - 4] = d[2];
    _buffer[_cursor_begin - 3] = d[3];
    #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    _buffer[_cursor_begin - 6] = d[3];
    _buffer[_cursor_begin - 5] = d[2];
    _buffer[_cursor_begin - 4] = d[1];
    _buffer[_cursor_begin - 3] = d[0];
    #else
    #error "byte orden not suported (PDP endian)"
    #endif

    {
        uint16_t st = status;
        d = (uint8_t*)&st;
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        _buffer[_cursor_begin - 2] = d[0];
        _buffer[_cursor_begin - 1] = d[1];
        #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
        _buffer[_cursor_begin - 2] = d[1];
        _buffer[_cursor_begin - 1] = d[0];
        #else
        #error "byte orden not suported (PDP endian)"
        #endif
    }
    //envoyer
    int res = Socket::send(_buffer+_cursor_begin-HEADER_SIZE, HEADER_SIZE+size);
    //reset
    //clear();
    return res;
};

int SocketSerialized::receive()
{
    //recuperer la taille dans les 6 premier oct
    int res = Socket::receive(_buffer,HEADER_SIZE);
    if (res > 0)
    {
        uint32_t size;
        {
            uint8_t d[4];
            #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
            d[0]= _buffer[0];
            d[1]= _buffer[1];
            d[2]= _buffer[2];
            d[3]= _buffer[3];
            #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
            d[3]= _buffer[0];
            d[2]= _buffer[1];
            d[1]= _buffer[2];
            d[0]= _buffer[3];
            #else
            #error "byte orden not suported (PDP endian)"
            #endif
            size = *(uint32_t*)&d;
        }

        {
            uint8_t d[2];
            #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
            d[0]= _buffer[4];
            d[1]= _buffer[5];
            #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
            d[1]= _buffer[4];
            d[0]= _buffer[5];
            #else
            #error "byte orden not suported (PDP endian)"
            #endif
            status = *(uint16_t*)&d;
        }

        //reset
        if (int(_buffer_size) < (int)HEADER_SIZE+(int)size)
            resize(HEADER_SIZE+size);
        //else _buffer_size ne change pas
        _cursor_begin = HEADER_SIZE;
        _cursor_end = HEADER_SIZE+size;
        //remplacer le buffer
        if(size>0)
        {
            int recv_left = size;
            int recv = 0;
            while(recv_left > 0)
            {
                recv = Socket::receive(_buffer+res,recv_left);
                if(recv<=0)
                    //TODO ERROR
                    break;
                res+=recv;
                recv_left -=recv;
            }
        }
    }
    else
    {
        clear();
        setStatus(NTW_STOP_CONNEXION);
    }
    return res;
};

void SocketSerialized::setStatus(short int st)
{
    status = st;
}

short int SocketSerialized::getStatus()const
{
    return status;
}

void SocketSerialized::clear()
{
    _cursor_begin = _cursor_end = HEADER_SIZE;
}

std::ostream& operator<<(std::ostream& output,const SocketSerialized& self)
{
    output<<"[id("<<self.id()<<"),size("<<self.size()<<"),status("<<self.status<<")]";
    for(unsigned int i=self._cursor_begin; i<self._cursor_end;++i)
    {
        if(self._buffer[i] < 33 or self._buffer[i] >126)
            output<<"<"<<(int)self._buffer[i]<<">";
        else
            output<<"'"<<(char)self._buffer[i]<<"'";
    }
    return output;
};

};
<|endoftext|>