<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "cluceneindexwriter.h"
#include "tcharutils.h"
#include <CLucene.h>
#include <CLucene/store/Lock.h>
#include "cluceneindexreader.h"
#include "cluceneindexmanager.h"
#include <CLucene/util/stringreader.h>
#include <sstream>
#include <assert.h>

#ifdef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
#include "jsgzipcompressstream.h"
#endif

#include <iostream>

using lucene::document::Document;
using lucene::document::Field;
using lucene::index::IndexWriter;
using lucene::index::Term;
using lucene::index::TermDocs;
using lucene::search::IndexSearcher;
using lucene::search::Hits;
using lucene::util::BitSet;

using lucene::util::Reader;
using namespace std;
using namespace Strigi;

struct CLuceneDocData {
    lucene::document::Document doc;
    std::string content;
};

CLuceneIndexWriter::CLuceneIndexWriter(CLuceneIndexManager* m):
    manager(m), doccount(0) {
    string contentID(FieldRegister::contentFieldName.c_str());
    wstring cID(utf8toucs2(contentID));
    addMapping(_T(""),cID.c_str());
}
CLuceneIndexWriter::~CLuceneIndexWriter() {
}
const wchar_t*
CLuceneIndexWriter::systemlocation() {
    const static wstring s(utf8toucs2(FieldRegister::pathFieldName));
    return s.c_str();
}
void
CLuceneIndexWriter::addText(const AnalysisResult* idx, const char* text,
        int32_t length) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->writerData());
    doc->content.append(text, length);
}

#ifdef _UCS2
typedef map<wstring, wstring> CLuceneIndexWriterFieldMapType;
#else
typedef map<string, string> CLuceneIndexWriterFieldMapType;
#endif
CLuceneIndexWriterFieldMapType CLuceneIndexWriterFieldMap;

void CLuceneIndexWriter::addMapping(const TCHAR* from, const TCHAR* to){
    CLuceneIndexWriterFieldMap[from] = to;
}
const TCHAR*
CLuceneIndexWriter::mapId(const TCHAR* id) {
    if (id == 0) id = _T("");
    CLuceneIndexWriterFieldMapType::iterator itr
        = CLuceneIndexWriterFieldMap.find(id);
    if (itr == CLuceneIndexWriterFieldMap.end()) {
        return id;
    } else {
        return itr->second.c_str();
    }
}
void
CLuceneIndexWriter::addValue(const AnalysisResult* idx,
        AnalyzerConfiguration::FieldType type, const TCHAR* name,
        const TCHAR* value) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->writerData());
    Field* field = new Field(name, value,
        (type & AnalyzerConfiguration::Stored) == AnalyzerConfiguration::Stored,
        (type & AnalyzerConfiguration::Indexed) == AnalyzerConfiguration::Indexed,
        (type & AnalyzerConfiguration::Tokenized) == AnalyzerConfiguration::Tokenized);
    doc->doc.add(*field);
}
void
CLuceneIndexWriter::addValue(const AnalysisResult* idx,
        AnalyzerConfiguration::FieldType type, const TCHAR* fn,
        const std::string& value) {
#if defined(_UCS2)
    addValue(idx, type, CLuceneIndexWriter::mapId(fn),
        utf8toucs2(value).c_str());
#else
    addValue(idx, type, CLuceneIndexWriter::mapId(fn), value.c_str());
#endif
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, const std::string& value) {
    AnalyzerConfiguration::FieldType type
        = idx->config().indexType(field);
    if (type == AnalyzerConfiguration::None) return;
#if defined(_UCS2)
    addValue(idx, type, utf8toucs2(field->key()).c_str(), value);
#else
    addValue(idx, type, field->key(), value);
#endif
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, uint32_t value) {
    ostringstream o;
    o << value;
    addValue(idx, field, o.str());
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, int32_t value) {
    ostringstream o;
    o << value;
    addValue(idx, field, o.str());
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field,
        const unsigned char* data, uint32_t size) {
    addValue(idx, field, string((const char*)data, (string::size_type)size));
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, double value) {
    ostringstream o;
    o << value;
    addValue(idx, field, o.str());
}
void
CLuceneIndexWriter::startAnalysis(const AnalysisResult* idx) {
    doccount++;
    CLuceneDocData*doc = new CLuceneDocData();
    idx->setWriterData(doc);
}
/*
    Close all left open indexwriters for this path.
*/
void
CLuceneIndexWriter::finishAnalysis(const AnalysisResult* idx) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->writerData());
    wstring c(utf8toucs2(doc->content));
    jstreams::StringReader<char>* sr = NULL; //we use this for compressed streams

    if (doc->content.length() > 0) {
        const TCHAR* mappedFn = mapId(_T(""));
#if defined(_UCS2)
    #ifndef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
        doc->doc.add(*Field::Text(mappedFn, c.c_str(), false));
    #else
        // lets store the content as utf8. remember, the stream is required
        // until the document is added, so a static construction of stringreader
        // is not good enough
        sr = new jstreams::StringReader<char>(doc->content.c_str(), doc->content.length(), false);

    // add the stored field with the zipstream
    doc->doc.add(*new Field(mappedFn, new jstreams::GZipCompressInputStream(sr),
        Field::STORE_YES));

    // add the tokenized/indexed field
    doc->doc.add(*new Field::Text(mappedFn, c.c_str(),
            Field::STORE_NO | Field::INDEX_TOKENIZED));
    #endif
#else //_UCS2
        doc->doc.add(*Field::Text(mappedFn, doc->content.c_str()) );
#endif
    }
    lucene::index::IndexWriter* writer = manager->refWriter();
    if (writer) {
        try {
            writer->addDocument(&doc->doc);
        } catch (CLuceneError& err) {
            fprintf(stderr, "%s: %s\n", idx->path().c_str(), err.what());
        }
    }
    manager->derefWriter();
    delete doc;
    if ( sr )
        delete sr;
    manager->setIndexMTime();
}
void
CLuceneIndexWriter::deleteEntries(const std::vector<std::string>& entries) {
    manager->closeWriter();
    if (!manager->luceneReader()->checkReader()) {
        fprintf(stderr,"cannot delete entry: lucene reader cannot be opened\n");
        return;
    }
    lucene::index::IndexReader* reader = manager->luceneReader()->reader;

    for (uint i=0; i<entries.size(); ++i) {
        deleteEntry(entries[i], reader);
    }
    reader->commit();
    manager->setIndexMTime();
}
void
CLuceneIndexWriter::deleteEntry(const string& entry,
        lucene::index::IndexReader* reader) {

    wstring tstr(utf8toucs2(entry));
    int32_t prefixLen = tstr.length();
    const TCHAR* prefixText = tstr.c_str();
    int32_t maxdoc = reader->maxDoc();
    for (int32_t i = 0; i < maxdoc; ++i) {
        if (!reader->isDeleted(i)) {
            Document* d = reader->document(i);
            const TCHAR* t = d->get(systemlocation());
            if (t && _tcsncmp(t, prefixText, prefixLen) == 0) {
                try {
                    reader->deleteDocument(i);
                } catch (...) {
                    cerr << "Could not delete document '" << entry
                        << "' from the index." << endl;
                }
            }
            _CLDELETE(d);
        }
    }
}
void
CLuceneIndexWriter::deleteAllEntries() {
    manager->deleteIndex();
}
void
CLuceneIndexWriter::commit() {
    manager->closeWriter();
}

//this function is in 0.9.17, which we do not have yet...
bool isLuceneFile(const char* filename){
    if ( !filename )
        return false;
    size_t len = strlen(filename);
    if ( len < 6 ) //need at least x.frx
        return false;
    const char* ext = filename + len;
    while ( *ext != '.' && ext != filename )
        ext--;

    if ( strcmp(ext, ".cfs") == 0 )
        return true;
    else if ( strcmp(ext, ".fnm") == 0 )
        return true;
    else if ( strcmp(ext, ".fdx") == 0 )
        return true;
    else if ( strcmp(ext, ".fdt") == 0 )
        return true;
    else if ( strcmp(ext, ".tii") == 0 )
        return true;
    else if ( strcmp(ext, ".tis") == 0 )
        return true;
    else if ( strcmp(ext, ".frq") == 0 )
        return true;
    else if ( strcmp(ext, ".prx") == 0 )
        return true;
    else if ( strcmp(ext, ".del") == 0 )
        return true;
    else if ( strcmp(ext, ".tvx") == 0 )
        return true;
    else if ( strcmp(ext, ".tvd") == 0 )
        return true;
    else if ( strcmp(ext, ".tvf") == 0 )
        return true;
    else if ( strcmp(ext, ".tvp") == 0 )
        return true;

    else if ( strcmp(filename, "segments") == 0 )
        return true;
    else if ( strcmp(filename, "segments.new") == 0 )
        return true;
    else if ( strcmp(filename, "deletable") == 0 )
        return true;

    else if ( strncmp(ext,".f",2)==0 ){
        const char* n = ext+2;
        if ( *n && _istdigit(*n) )
            return true;
    }

    return false;
}

void
CLuceneIndexWriter::cleanUp() {
    // remove all unused lucene file elements...
    // unused elements are the result of unexpected shutdowns...
    // this can add up to a lot of after a while.

    lucene::index::IndexReader* reader = manager->luceneReader()->reader;
    if (!reader) {
        return;
    }
    lucene::store::Directory* directory = reader->getDirectory();

    // Instantiate SegmentInfos
    lucene::store::LuceneLock* lock = directory->makeLock("commit.lock");
#ifdef LUCENE_COMMIT_LOCK_TIMEOUT
    // version <0.9.16
    bool locked = lock->obtain(LUCENE_COMMIT_LOCK_TIMEOUT);
#else
    bool locked = lock->obtain(lucene::index::IndexWriter::COMMIT_LOCK_TIMEOUT);
#endif
    if (!locked) {
        return;
    }
    lucene::index::SegmentInfos infos;
    try {
        //Have SegmentInfos read the segments file in directory
        infos.read(directory);
    } catch(...) {
        lock->release();
        return; //todo: this may suggest an error...
    }
    lock->release();

    int i;
    set<string> segments;
    for (i = 0; i < infos.size(); i++) {
            lucene::index::SegmentInfo* info = infos.info(i);
            segments.insert(info->name);
    }

    char** files = directory->list();
    char tmp[CL_MAX_PATH];
    for (i = 0; files[i] != NULL; ++i) {
        char* file = files[i];

        int fileLength = strlen(file);
        if ( fileLength < 6 ) {
            continue;
        }

        if (strncmp(file,"segments", 8) == 0
                || strncmp(file, "deletable", 9) == 0) {
            continue;
        }
        if (!isLuceneFile(file)) {
            continue;
        }

        strcpy(tmp, file);
        tmp[fileLength-4] = '\0';

        if (segments.find(tmp) != segments.end()) {
            continue;
        }

        directory->deleteFile(file, false);
    }
    for (i = 0; files[i] != NULL; i++) {
        _CLDELETE_CaARRAY(files[i]);
    }
    _CLDELETE_ARRAY(files);
}

void
CLuceneIndexWriter::initWriterData(const FieldRegister& f) {
    map<string, RegisteredField*>::const_iterator i;
    map<string, RegisteredField*>::const_iterator end = f.fields().end();
    for (i = f.fields().begin(); i != end; ++i) {
        i->second->setWriterData(0);
    }
}
void
CLuceneIndexWriter::releaseWriterData(const FieldRegister& f) {
    map<string, RegisteredField*>::const_iterator i;
    map<string, RegisteredField*>::const_iterator end = f.fields().end();
    for (i = f.fields().begin(); i != end; ++i) {
        delete static_cast<int*>(i->second->writerData());
    }
}
<commit_msg>Make error report more precise.<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "cluceneindexwriter.h"
#include "tcharutils.h"
#include <CLucene.h>
#include <CLucene/store/Lock.h>
#include "cluceneindexreader.h"
#include "cluceneindexmanager.h"
#include <CLucene/util/stringreader.h>
#include <sstream>
#include <assert.h>

#ifdef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
#include "jsgzipcompressstream.h"
#endif

#include <iostream>

using lucene::document::Document;
using lucene::document::Field;
using lucene::index::IndexWriter;
using lucene::index::Term;
using lucene::index::TermDocs;
using lucene::search::IndexSearcher;
using lucene::search::Hits;
using lucene::util::BitSet;

using lucene::util::Reader;
using namespace std;
using namespace Strigi;

struct CLuceneDocData {
    lucene::document::Document doc;
    std::string content;
};

CLuceneIndexWriter::CLuceneIndexWriter(CLuceneIndexManager* m):
    manager(m), doccount(0) {
    string contentID(FieldRegister::contentFieldName.c_str());
    wstring cID(utf8toucs2(contentID));
    addMapping(_T(""),cID.c_str());
}
CLuceneIndexWriter::~CLuceneIndexWriter() {
}
const wchar_t*
CLuceneIndexWriter::systemlocation() {
    const static wstring s(utf8toucs2(FieldRegister::pathFieldName));
    return s.c_str();
}
void
CLuceneIndexWriter::addText(const AnalysisResult* idx, const char* text,
        int32_t length) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->writerData());
    doc->content.append(text, length);
}

#ifdef _UCS2
typedef map<wstring, wstring> CLuceneIndexWriterFieldMapType;
#else
typedef map<string, string> CLuceneIndexWriterFieldMapType;
#endif
CLuceneIndexWriterFieldMapType CLuceneIndexWriterFieldMap;

void CLuceneIndexWriter::addMapping(const TCHAR* from, const TCHAR* to){
    CLuceneIndexWriterFieldMap[from] = to;
}
const TCHAR*
CLuceneIndexWriter::mapId(const TCHAR* id) {
    if (id == 0) id = _T("");
    CLuceneIndexWriterFieldMapType::iterator itr
        = CLuceneIndexWriterFieldMap.find(id);
    if (itr == CLuceneIndexWriterFieldMap.end()) {
        return id;
    } else {
        return itr->second.c_str();
    }
}
void
CLuceneIndexWriter::addValue(const AnalysisResult* idx,
        AnalyzerConfiguration::FieldType type, const TCHAR* name,
        const TCHAR* value) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->writerData());
    Field* field = new Field(name, value,
        (type & AnalyzerConfiguration::Stored) == AnalyzerConfiguration::Stored,
        (type & AnalyzerConfiguration::Indexed) == AnalyzerConfiguration::Indexed,
        (type & AnalyzerConfiguration::Tokenized) == AnalyzerConfiguration::Tokenized);
    doc->doc.add(*field);
}
void
CLuceneIndexWriter::addValue(const AnalysisResult* idx,
        AnalyzerConfiguration::FieldType type, const TCHAR* fn,
        const std::string& value) {
#if defined(_UCS2)
    addValue(idx, type, CLuceneIndexWriter::mapId(fn),
        utf8toucs2(value).c_str());
#else
    addValue(idx, type, CLuceneIndexWriter::mapId(fn), value.c_str());
#endif
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, const std::string& value) {
    AnalyzerConfiguration::FieldType type
        = idx->config().indexType(field);
    if (type == AnalyzerConfiguration::None) return;
#if defined(_UCS2)
    addValue(idx, type, utf8toucs2(field->key()).c_str(), value);
#else
    addValue(idx, type, field->key(), value);
#endif
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, uint32_t value) {
    ostringstream o;
    o << value;
    addValue(idx, field, o.str());
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, int32_t value) {
    ostringstream o;
    o << value;
    addValue(idx, field, o.str());
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field,
        const unsigned char* data, uint32_t size) {
    addValue(idx, field, string((const char*)data, (string::size_type)size));
}
void
CLuceneIndexWriter::addValue(const Strigi::AnalysisResult* idx,
        const Strigi::RegisteredField* field, double value) {
    ostringstream o;
    o << value;
    addValue(idx, field, o.str());
}
void
CLuceneIndexWriter::startAnalysis(const AnalysisResult* idx) {
    doccount++;
    CLuceneDocData*doc = new CLuceneDocData();
    idx->setWriterData(doc);
}
/*
    Close all left open indexwriters for this path.
*/
void
CLuceneIndexWriter::finishAnalysis(const AnalysisResult* idx) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->writerData());
    wstring c(utf8toucs2(doc->content));
    jstreams::StringReader<char>* sr = NULL; //we use this for compressed streams

    if (doc->content.length() > 0) {
        const TCHAR* mappedFn = mapId(_T(""));
#if defined(_UCS2)
    #ifndef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
        doc->doc.add(*Field::Text(mappedFn, c.c_str(), false));
    #else
        // lets store the content as utf8. remember, the stream is required
        // until the document is added, so a static construction of stringreader
        // is not good enough
        sr = new jstreams::StringReader<char>(doc->content.c_str(), doc->content.length(), false);

    // add the stored field with the zipstream
    doc->doc.add(*new Field(mappedFn, new jstreams::GZipCompressInputStream(sr),
        Field::STORE_YES));

    // add the tokenized/indexed field
    doc->doc.add(*new Field::Text(mappedFn, c.c_str(),
            Field::STORE_NO | Field::INDEX_TOKENIZED));
    #endif
#else //_UCS2
        doc->doc.add(*Field::Text(mappedFn, doc->content.c_str()) );
#endif
    }
    lucene::index::IndexWriter* writer = manager->refWriter();
    if (writer) {
        try {
            writer->addDocument(&doc->doc);
        } catch (CLuceneError& err) {
            fprintf(stderr, "%s: %s\n", idx->path().c_str(), err.what());
        }
    }
    manager->derefWriter();
    delete doc;
    if ( sr )
        delete sr;
    manager->setIndexMTime();
}
void
CLuceneIndexWriter::deleteEntries(const std::vector<std::string>& entries) {
    manager->closeWriter();
    if (!manager->luceneReader()->checkReader()) {
        fprintf(stderr,"cannot delete entry: lucene reader cannot be opened\n");
        return;
    }
    lucene::index::IndexReader* reader = manager->luceneReader()->reader;

    for (uint i=0; i<entries.size(); ++i) {
        deleteEntry(entries[i], reader);
    }
    reader->commit();
    manager->setIndexMTime();
}
void
CLuceneIndexWriter::deleteEntry(const string& entry,
        lucene::index::IndexReader* reader) {

    wstring tstr(utf8toucs2(entry));
    int32_t prefixLen = tstr.length();
    const TCHAR* prefixText = tstr.c_str();
    int32_t maxdoc = reader->maxDoc();
    for (int32_t i = 0; i < maxdoc; ++i) {
        if (!reader->isDeleted(i)) {
            Document* d = reader->document(i);
            const TCHAR* t = d->get(systemlocation());
            if (t && _tcsncmp(t, prefixText, prefixLen) == 0) {
                try {
                    reader->deleteDocument(i);
                } catch (CLuceneError& err) {
                    cerr << "Could not delete document '" << entry
                        << "' from the index: " << err.what() << endl;
                } catch (...) {
                    cerr << "This should not happen." << endl;
                }
            }
            _CLDELETE(d);
        }
    }
}
void
CLuceneIndexWriter::deleteAllEntries() {
    manager->deleteIndex();
}
void
CLuceneIndexWriter::commit() {
    manager->closeWriter();
}

//this function is in 0.9.17, which we do not have yet...
bool isLuceneFile(const char* filename){
    if ( !filename )
        return false;
    size_t len = strlen(filename);
    if ( len < 6 ) //need at least x.frx
        return false;
    const char* ext = filename + len;
    while ( *ext != '.' && ext != filename )
        ext--;

    if ( strcmp(ext, ".cfs") == 0 )
        return true;
    else if ( strcmp(ext, ".fnm") == 0 )
        return true;
    else if ( strcmp(ext, ".fdx") == 0 )
        return true;
    else if ( strcmp(ext, ".fdt") == 0 )
        return true;
    else if ( strcmp(ext, ".tii") == 0 )
        return true;
    else if ( strcmp(ext, ".tis") == 0 )
        return true;
    else if ( strcmp(ext, ".frq") == 0 )
        return true;
    else if ( strcmp(ext, ".prx") == 0 )
        return true;
    else if ( strcmp(ext, ".del") == 0 )
        return true;
    else if ( strcmp(ext, ".tvx") == 0 )
        return true;
    else if ( strcmp(ext, ".tvd") == 0 )
        return true;
    else if ( strcmp(ext, ".tvf") == 0 )
        return true;
    else if ( strcmp(ext, ".tvp") == 0 )
        return true;

    else if ( strcmp(filename, "segments") == 0 )
        return true;
    else if ( strcmp(filename, "segments.new") == 0 )
        return true;
    else if ( strcmp(filename, "deletable") == 0 )
        return true;

    else if ( strncmp(ext,".f",2)==0 ){
        const char* n = ext+2;
        if ( *n && _istdigit(*n) )
            return true;
    }

    return false;
}

void
CLuceneIndexWriter::cleanUp() {
    // remove all unused lucene file elements...
    // unused elements are the result of unexpected shutdowns...
    // this can add up to a lot of after a while.

    lucene::index::IndexReader* reader = manager->luceneReader()->reader;
    if (!reader) {
        return;
    }
    lucene::store::Directory* directory = reader->getDirectory();

    // Instantiate SegmentInfos
    lucene::store::LuceneLock* lock = directory->makeLock("commit.lock");
#ifdef LUCENE_COMMIT_LOCK_TIMEOUT
    // version <0.9.16
    bool locked = lock->obtain(LUCENE_COMMIT_LOCK_TIMEOUT);
#else
    bool locked = lock->obtain(lucene::index::IndexWriter::COMMIT_LOCK_TIMEOUT);
#endif
    if (!locked) {
        return;
    }
    lucene::index::SegmentInfos infos;
    try {
        //Have SegmentInfos read the segments file in directory
        infos.read(directory);
    } catch(...) {
        lock->release();
        return; //todo: this may suggest an error...
    }
    lock->release();

    int i;
    set<string> segments;
    for (i = 0; i < infos.size(); i++) {
            lucene::index::SegmentInfo* info = infos.info(i);
            segments.insert(info->name);
    }

    char** files = directory->list();
    char tmp[CL_MAX_PATH];
    for (i = 0; files[i] != NULL; ++i) {
        char* file = files[i];

        int fileLength = strlen(file);
        if ( fileLength < 6 ) {
            continue;
        }

        if (strncmp(file,"segments", 8) == 0
                || strncmp(file, "deletable", 9) == 0) {
            continue;
        }
        if (!isLuceneFile(file)) {
            continue;
        }

        strcpy(tmp, file);
        tmp[fileLength-4] = '\0';

        if (segments.find(tmp) != segments.end()) {
            continue;
        }

        directory->deleteFile(file, false);
    }
    for (i = 0; files[i] != NULL; i++) {
        _CLDELETE_CaARRAY(files[i]);
    }
    _CLDELETE_ARRAY(files);
}

void
CLuceneIndexWriter::initWriterData(const FieldRegister& f) {
    map<string, RegisteredField*>::const_iterator i;
    map<string, RegisteredField*>::const_iterator end = f.fields().end();
    for (i = f.fields().begin(); i != end; ++i) {
        i->second->setWriterData(0);
    }
}
void
CLuceneIndexWriter::releaseWriterData(const FieldRegister& f) {
    map<string, RegisteredField*>::const_iterator i;
    map<string, RegisteredField*>::const_iterator end = f.fields().end();
    for (i = f.fields().begin(); i != end; ++i) {
        delete static_cast<int*>(i->second->writerData());
    }
}
<|endoftext|>


<commit_before>/***************************************************************************
 * Copyright 1998-2013 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxRender.                                       *
 *                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License");         *
 * you may not use this file except in compliance with the License.        *
 * You may obtain a copy of the License at                                 *
 *                                                                         *
 *     http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                         *
 * Unless required by applicable law or agreed to in writing, software     *
 * distributed under the License is distributed on an "AS IS" BASIS,       *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 * See the License for the specific language governing permissions and     *
 * limitations under the License.                                          *
 ***************************************************************************/

#include <string>
#include <limits>

#if defined (_MSC_VER) || defined (__INTEL_COMPILER)
#include <intrin.h>
#endif

#include <boost/foreach.hpp>

#include "luxrays/core/context.h"
#include "luxrays/accelerators/embreeaccel.h"

namespace luxrays {

void Embree_error_handler(const RTCError code, const char *str) {
	std::string errType;

	switch (code) {
		case RTC_UNKNOWN_ERROR:
			errType = "RTC_UNKNOWN_ERROR";
			break;
		case RTC_INVALID_ARGUMENT:
			errType = "RTC_INVALID_ARGUMENT";
			break;
		case RTC_INVALID_OPERATION:
			errType = "RTC_INVALID_OPERATION";
			break;
		case RTC_OUT_OF_MEMORY:
			errType = "RTC_OUT_OF_MEMORY";
			break;
		case RTC_UNSUPPORTED_CPU:
			errType = "RTC_UNSUPPORTED_CPU";
			break;
		default:
			errType = "invalid error code";
			break;
	}

	std::cout << "Embree error: " << str << "\n";

	abort();
}

boost::mutex EmbreeAccel::initMutex;
u_int EmbreeAccel::initCount = 0;

EmbreeAccel::EmbreeAccel(const Context *context) : ctx(context) {
	embreeScene = NULL;

	// Initialize Embree
	boost::unique_lock<boost::mutex> lock(initMutex);
	if (initCount == 0) {
		rtcInit(NULL);
		rtcSetErrorFunction(Embree_error_handler);
	}
	++initCount;
}

EmbreeAccel::~EmbreeAccel() {
	if (embreeScene)
		rtcDeleteScene(embreeScene);

	// Shutdown Embree if I was the last one
	boost::unique_lock<boost::mutex> lock(initMutex);
	if (initCount == 1)
		rtcExit();
	--initCount;
}

static inline void cpuid(int output[4], int functionnumber) {
#if defined (_MSC_VER) || defined (__INTEL_COMPILER)       // Microsoft or Intel compiler, intrin.h included

		__cpuidex(output, functionnumber, 0); // intrinsic function for CPUID

#elif defined(__GNUC__) || defined(__clang__) // use inline assembly, Gnu/AT&T syntax

		int a, b, c, d;
		__asm("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(functionnumber), "c"(0) :);
		output[0] = a;
		output[1] = b;
		output[2] = c;
		output[3] = d;

#else                                         // unknown platform. try inline assembly with masm/intel syntax

		__asm{
			mov eax, functionnumber
			xor ecx, ecx
			cpuid;
			mov esi, output
			mov [esi], eax
			mov [esi + 4], ebx
			mov [esi + 8], ecx
			mov [esi + 12], edx
		}

#endif
}

u_int EmbreeAccel::ExportTriangleMesh(const RTCScene embreeScene, const Mesh *mesh) const {
	const u_int geomID = rtcNewTriangleMesh(embreeScene, RTC_GEOMETRY_STATIC,
			mesh->GetTotalTriangleCount(), mesh->GetTotalVertexCount(), 1);

	//--------------------------------------------------------------------------
	// I have to check if I'm not running on an AVX-enabled CPU in order to
	// implement a workaround to this Embree bug: https://software.intel.com/en-us/forums/topic/536085

//	bool avxSupported = false;
	// Checking for AVX requires 3 things:
    // 1) CPUID indicates that the OS uses XSAVE and XRSTORE
    //     instructions (allowing saving YMM registers on context
    //     switch)
    // 2) CPUID indicates support for AVX
    // 3) XGETBV indicates the AVX registers will be saved and
    //     restored on context switch
	//
	// Note: I'm skipping #3. I assume that the OS does.
    //
    // Note that XGETBV is only available on 686 or later CPUs, so
    // the instruction needs to be conditionally run.
//    int cpuInfo[4];
//	cpuid(cpuInfo, 1);
//
//	const bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
//	const bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;
//
//	/*if (osUsesXSAVE_XRSTORE && cpuAVXSuport) {
//		// Check if the OS will save the YMM registers
//		unsigned long long xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
//		avxSupported = (xcrFeatureMask & 0x6) || false;
//	}*/
//
//	avxSupported = osUsesXSAVE_XRSTORE && cpuAVXSuport;

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

//	if (avxSupported) {
		// Share the mesh vertices
		Point *meshVerts = mesh->GetVertices();
		rtcSetBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER, meshVerts, 0, 3 * sizeof(float));
//	} else {
//		LR_LOG(ctx, "WARNING: detected a not AVX-capable CPU, using workaround to Embree bug");
//
//		float *vertices = (float *)rtcMapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER);
//
//		const Point *meshVerts = mesh->GetVertices();
//		for (u_int i = 0; i < mesh->GetTotalVertexCount(); ++i) {
//			*vertices++ = meshVerts->x;
//			*vertices++ = meshVerts->y;
//			*vertices++ = meshVerts->z;
//			*vertices++ = 0.f;
//
//			++meshVerts;
//		}
//
//		rtcUnmapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER);
//	}

	// Share the mesh triangles
	Triangle *meshTris = mesh->GetTriangles();
	rtcSetBuffer(embreeScene, geomID, RTC_INDEX_BUFFER, meshTris, 0, 3 * sizeof(int));

	return geomID;
}

u_int EmbreeAccel::ExportMotionTriangleMesh(const RTCScene embreeScene, const MotionTriangleMesh *mtm) const {
	const u_int geomID = rtcNewTriangleMesh(embreeScene, RTC_GEOMETRY_STATIC,
			mtm->GetTotalTriangleCount(), mtm->GetTotalVertexCount(), 2);

	const MotionSystem &ms = mtm->GetMotionSystem();

	// Copy the mesh start position vertices
	float *vertices0 = (float *)rtcMapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER0);
	for (u_int i = 0; i < mtm->GetTotalVertexCount(); ++i) {
		const Point v = mtm->GetVertex(ms.StartTime(), i);
		*vertices0++ = v.x;
		*vertices0++ = v.y;
		*vertices0++ = v.z;
		++vertices0;
	}
	rtcUnmapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER0);

	// Copy the mesh end position vertices
	float *vertices1 = (float *)rtcMapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER1);
	for (u_int i = 0; i < mtm->GetTotalVertexCount(); ++i) {
		const Point v = mtm->GetVertex(ms.EndTime(), i);
		*vertices1++ = v.x;
		*vertices1++ = v.y;
		*vertices1++ = v.z;
		++vertices1;
	}
	rtcUnmapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER1);

	// Share the mesh triangles
	Triangle *meshTris = mtm->GetTriangles();
	rtcSetBuffer(embreeScene, geomID, RTC_INDEX_BUFFER, meshTris, 0, 3 * sizeof(int));

	return geomID;
}

void EmbreeAccel::Init(const std::deque<const Mesh *> &meshes,
		const u_longlong totalVertexCount,
		const u_longlong totalTriangleCount) {
	const double t0 = WallClockTime();

	//--------------------------------------------------------------------------
	// Extract the meshes min. and max. time. To normalize between 0.f and 1.f.
	//--------------------------------------------------------------------------

	minTime = std::numeric_limits<float>::max();
	maxTime = std::numeric_limits<float>::min();
	BOOST_FOREACH(const Mesh *mesh, meshes) {
		const MotionTriangleMesh *mtm = dynamic_cast<const MotionTriangleMesh *>(mesh);

		if (mtm) {
			minTime = Min(minTime, mtm->GetMotionSystem().StartTime());
			maxTime = Min(maxTime, mtm->GetMotionSystem().EndTime());
		}
	}

	if ((minTime == std::numeric_limits<float>::max()) ||
			(maxTime == std::numeric_limits<float>::min())) {
		minTime = 0.f;
		maxTime = 1.f;
		timeScale = 1.f;
	} else
		timeScale = 1.f / (maxTime - minTime);

	//--------------------------------------------------------------------------
	// Convert the meshes to an Embree Scene
	//--------------------------------------------------------------------------

	embreeScene = rtcNewScene(RTC_SCENE_STATIC, RTC_INTERSECT1);

	std::map<const Mesh *, RTCScene, bool (*)(const Mesh *, const Mesh *)> uniqueRTCSceneByMesh(MeshPtrCompare);

	BOOST_FOREACH(const Mesh *mesh, meshes) {
		switch (mesh->GetType()) {
			case TYPE_TRIANGLE:
			case TYPE_EXT_TRIANGLE:
				ExportTriangleMesh(embreeScene, mesh);
				break;
			case TYPE_TRIANGLE_INSTANCE:
			case TYPE_EXT_TRIANGLE_INSTANCE: {
				const InstanceTriangleMesh *itm = dynamic_cast<const InstanceTriangleMesh *>(mesh);

				// Check if a RTCScene has already been created
				std::map<const Mesh *, RTCScene, bool (*)(const Mesh *, const Mesh *)>::iterator it =
						uniqueRTCSceneByMesh.find(itm->GetTriangleMesh());

				RTCScene instScene;
				if (it == uniqueRTCSceneByMesh.end()) {
					TriangleMesh *instancedMesh = itm->GetTriangleMesh();

					// Create a new RTCScene
					instScene = rtcNewScene(RTC_SCENE_STATIC, RTC_INTERSECT1);
					ExportTriangleMesh(instScene, instancedMesh);
					rtcCommit(instScene);

					uniqueRTCSceneByMesh[instancedMesh] = instScene;
				} else
					instScene = it->second;

				const u_int instID = rtcNewInstance(embreeScene, instScene);
				rtcSetTransform(embreeScene, instID, RTC_MATRIX_ROW_MAJOR, &(itm->GetTransformation().m.m[0][0]));
				break;
			}
			case TYPE_TRIANGLE_MOTION:
			case TYPE_EXT_TRIANGLE_MOTION: {
				const MotionTriangleMesh *mtm = dynamic_cast<const MotionTriangleMesh *>(mesh);
				ExportMotionTriangleMesh(embreeScene, mtm);
				break;
			}
			default:
				throw std::runtime_error("Unknown Mesh type in EmbreeAccel::Init(): " + ToString(mesh->GetType()));
		}
	}

	rtcCommit(embreeScene);

	LR_LOG(ctx, "EmbreeAccel build time: " << int((WallClockTime() - t0) * 1000) << "ms");
}

bool EmbreeAccel::MeshPtrCompare(const Mesh *p0, const Mesh *p1) {
	return p0 < p1;
}

bool EmbreeAccel::Intersect(const Ray *ray, RayHit *hit) const {
	RTCRay embreeRay;

	embreeRay.org[0] = ray->o.x;
	embreeRay.org[1] = ray->o.y;
	embreeRay.org[2] = ray->o.z;

	embreeRay.dir[0] = ray->d.x;
	embreeRay.dir[1] = ray->d.y;
	embreeRay.dir[2] = ray->d.z;

	embreeRay.tnear = ray->mint;
	embreeRay.tfar = ray->maxt;

	embreeRay.geomID = RTC_INVALID_GEOMETRY_ID;
	embreeRay.primID = RTC_INVALID_GEOMETRY_ID;
	embreeRay.instID = RTC_INVALID_GEOMETRY_ID;
	embreeRay.mask = 0xFFFFFFFF;
	embreeRay.time = (ray->time - minTime) * timeScale;

	rtcIntersect(embreeScene, embreeRay);

	if (embreeRay.geomID != RTC_INVALID_GEOMETRY_ID) {
		hit->meshIndex = (embreeRay.instID == RTC_INVALID_GEOMETRY_ID) ? embreeRay.geomID : embreeRay.instID;
		hit->triangleIndex = embreeRay.primID;

		hit->t = embreeRay.tfar;

		hit->b1 = embreeRay.u;
		hit->b2 = embreeRay.v;

		return true;
	} else
		return false;
}

}
<commit_msg>Removed the disabled work around for Embree 2.3.3 bug<commit_after>/***************************************************************************
 * Copyright 1998-2013 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxRender.                                       *
 *                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License");         *
 * you may not use this file except in compliance with the License.        *
 * You may obtain a copy of the License at                                 *
 *                                                                         *
 *     http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                         *
 * Unless required by applicable law or agreed to in writing, software     *
 * distributed under the License is distributed on an "AS IS" BASIS,       *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 * See the License for the specific language governing permissions and     *
 * limitations under the License.                                          *
 ***************************************************************************/

#include <string>
#include <limits>

#if defined (_MSC_VER) || defined (__INTEL_COMPILER)
#include <intrin.h>
#endif

#include <boost/foreach.hpp>

#include "luxrays/core/context.h"
#include "luxrays/accelerators/embreeaccel.h"

namespace luxrays {

void Embree_error_handler(const RTCError code, const char *str) {
	std::string errType;

	switch (code) {
		case RTC_UNKNOWN_ERROR:
			errType = "RTC_UNKNOWN_ERROR";
			break;
		case RTC_INVALID_ARGUMENT:
			errType = "RTC_INVALID_ARGUMENT";
			break;
		case RTC_INVALID_OPERATION:
			errType = "RTC_INVALID_OPERATION";
			break;
		case RTC_OUT_OF_MEMORY:
			errType = "RTC_OUT_OF_MEMORY";
			break;
		case RTC_UNSUPPORTED_CPU:
			errType = "RTC_UNSUPPORTED_CPU";
			break;
		default:
			errType = "invalid error code";
			break;
	}

	std::cout << "Embree error: " << str << "\n";

	abort();
}

boost::mutex EmbreeAccel::initMutex;
u_int EmbreeAccel::initCount = 0;

EmbreeAccel::EmbreeAccel(const Context *context) : ctx(context) {
	embreeScene = NULL;

	// Initialize Embree
	boost::unique_lock<boost::mutex> lock(initMutex);
	if (initCount == 0) {
		rtcInit(NULL);
		rtcSetErrorFunction(Embree_error_handler);
	}
	++initCount;
}

EmbreeAccel::~EmbreeAccel() {
	if (embreeScene)
		rtcDeleteScene(embreeScene);

	// Shutdown Embree if I was the last one
	boost::unique_lock<boost::mutex> lock(initMutex);
	if (initCount == 1)
		rtcExit();
	--initCount;
}

u_int EmbreeAccel::ExportTriangleMesh(const RTCScene embreeScene, const Mesh *mesh) const {
	const u_int geomID = rtcNewTriangleMesh(embreeScene, RTC_GEOMETRY_STATIC,
			mesh->GetTotalTriangleCount(), mesh->GetTotalVertexCount(), 1);

	// Share with Embree the mesh vertices
	Point *meshVerts = mesh->GetVertices();
	rtcSetBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER, meshVerts, 0, 3 * sizeof(float));

	// Share with Embree the mesh triangles
	Triangle *meshTris = mesh->GetTriangles();
	rtcSetBuffer(embreeScene, geomID, RTC_INDEX_BUFFER, meshTris, 0, 3 * sizeof(int));

	return geomID;
}

u_int EmbreeAccel::ExportMotionTriangleMesh(const RTCScene embreeScene, const MotionTriangleMesh *mtm) const {
	const u_int geomID = rtcNewTriangleMesh(embreeScene, RTC_GEOMETRY_STATIC,
			mtm->GetTotalTriangleCount(), mtm->GetTotalVertexCount(), 2);

	const MotionSystem &ms = mtm->GetMotionSystem();

	// Copy the mesh start position vertices
	float *vertices0 = (float *)rtcMapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER0);
	for (u_int i = 0; i < mtm->GetTotalVertexCount(); ++i) {
		const Point v = mtm->GetVertex(ms.StartTime(), i);
		*vertices0++ = v.x;
		*vertices0++ = v.y;
		*vertices0++ = v.z;
		++vertices0;
	}
	rtcUnmapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER0);

	// Copy the mesh end position vertices
	float *vertices1 = (float *)rtcMapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER1);
	for (u_int i = 0; i < mtm->GetTotalVertexCount(); ++i) {
		const Point v = mtm->GetVertex(ms.EndTime(), i);
		*vertices1++ = v.x;
		*vertices1++ = v.y;
		*vertices1++ = v.z;
		++vertices1;
	}
	rtcUnmapBuffer(embreeScene, geomID, RTC_VERTEX_BUFFER1);

	// Share the mesh triangles
	Triangle *meshTris = mtm->GetTriangles();
	rtcSetBuffer(embreeScene, geomID, RTC_INDEX_BUFFER, meshTris, 0, 3 * sizeof(int));

	return geomID;
}

void EmbreeAccel::Init(const std::deque<const Mesh *> &meshes,
		const u_longlong totalVertexCount,
		const u_longlong totalTriangleCount) {
	const double t0 = WallClockTime();

	//--------------------------------------------------------------------------
	// Extract the meshes min. and max. time. To normalize between 0.f and 1.f.
	//--------------------------------------------------------------------------

	minTime = std::numeric_limits<float>::max();
	maxTime = std::numeric_limits<float>::min();
	BOOST_FOREACH(const Mesh *mesh, meshes) {
		const MotionTriangleMesh *mtm = dynamic_cast<const MotionTriangleMesh *>(mesh);

		if (mtm) {
			minTime = Min(minTime, mtm->GetMotionSystem().StartTime());
			maxTime = Min(maxTime, mtm->GetMotionSystem().EndTime());
		}
	}

	if ((minTime == std::numeric_limits<float>::max()) ||
			(maxTime == std::numeric_limits<float>::min())) {
		minTime = 0.f;
		maxTime = 1.f;
		timeScale = 1.f;
	} else
		timeScale = 1.f / (maxTime - minTime);

	//--------------------------------------------------------------------------
	// Convert the meshes to an Embree Scene
	//--------------------------------------------------------------------------

	embreeScene = rtcNewScene(RTC_SCENE_STATIC, RTC_INTERSECT1);

	std::map<const Mesh *, RTCScene, bool (*)(const Mesh *, const Mesh *)> uniqueRTCSceneByMesh(MeshPtrCompare);

	BOOST_FOREACH(const Mesh *mesh, meshes) {
		switch (mesh->GetType()) {
			case TYPE_TRIANGLE:
			case TYPE_EXT_TRIANGLE:
				ExportTriangleMesh(embreeScene, mesh);
				break;
			case TYPE_TRIANGLE_INSTANCE:
			case TYPE_EXT_TRIANGLE_INSTANCE: {
				const InstanceTriangleMesh *itm = dynamic_cast<const InstanceTriangleMesh *>(mesh);

				// Check if a RTCScene has already been created
				std::map<const Mesh *, RTCScene, bool (*)(const Mesh *, const Mesh *)>::iterator it =
						uniqueRTCSceneByMesh.find(itm->GetTriangleMesh());

				RTCScene instScene;
				if (it == uniqueRTCSceneByMesh.end()) {
					TriangleMesh *instancedMesh = itm->GetTriangleMesh();

					// Create a new RTCScene
					instScene = rtcNewScene(RTC_SCENE_STATIC, RTC_INTERSECT1);
					ExportTriangleMesh(instScene, instancedMesh);
					rtcCommit(instScene);

					uniqueRTCSceneByMesh[instancedMesh] = instScene;
				} else
					instScene = it->second;

				const u_int instID = rtcNewInstance(embreeScene, instScene);
				rtcSetTransform(embreeScene, instID, RTC_MATRIX_ROW_MAJOR, &(itm->GetTransformation().m.m[0][0]));
				break;
			}
			case TYPE_TRIANGLE_MOTION:
			case TYPE_EXT_TRIANGLE_MOTION: {
				const MotionTriangleMesh *mtm = dynamic_cast<const MotionTriangleMesh *>(mesh);
				ExportMotionTriangleMesh(embreeScene, mtm);
				break;
			}
			default:
				throw std::runtime_error("Unknown Mesh type in EmbreeAccel::Init(): " + ToString(mesh->GetType()));
		}
	}

	rtcCommit(embreeScene);

	LR_LOG(ctx, "EmbreeAccel build time: " << int((WallClockTime() - t0) * 1000) << "ms");
}

bool EmbreeAccel::MeshPtrCompare(const Mesh *p0, const Mesh *p1) {
	return p0 < p1;
}

bool EmbreeAccel::Intersect(const Ray *ray, RayHit *hit) const {
	RTCRay embreeRay;

	embreeRay.org[0] = ray->o.x;
	embreeRay.org[1] = ray->o.y;
	embreeRay.org[2] = ray->o.z;

	embreeRay.dir[0] = ray->d.x;
	embreeRay.dir[1] = ray->d.y;
	embreeRay.dir[2] = ray->d.z;

	embreeRay.tnear = ray->mint;
	embreeRay.tfar = ray->maxt;

	embreeRay.geomID = RTC_INVALID_GEOMETRY_ID;
	embreeRay.primID = RTC_INVALID_GEOMETRY_ID;
	embreeRay.instID = RTC_INVALID_GEOMETRY_ID;
	embreeRay.mask = 0xFFFFFFFF;
	embreeRay.time = (ray->time - minTime) * timeScale;

	rtcIntersect(embreeScene, embreeRay);

	if (embreeRay.geomID != RTC_INVALID_GEOMETRY_ID) {
		hit->meshIndex = (embreeRay.instID == RTC_INVALID_GEOMETRY_ID) ? embreeRay.geomID : embreeRay.instID;
		hit->triangleIndex = embreeRay.primID;

		hit->t = embreeRay.tfar;

		hit->b1 = embreeRay.u;
		hit->b2 = embreeRay.v;

		return true;
	} else
		return false;
}

}
<|endoftext|>


<commit_before>#ifndef ALGORITHM
#define ALGORITHM
#include<algorithm>	//move
#include<cstddef>
#include<functional>	//bind, placeholders
#include<iterator>
#include<type_traits>	//make_unsigned
#include<utility>	//move
#include"../thread/CSmartThread.hpp"

namespace nAlgorithm
{
	template<class T,class UnaryPred>
	bool all_of_val(T begin,const T end,const UnaryPred pred)
	{
		while(begin!=end)
		{
			if(!pred(begin))
				return false;
			++begin;
		}
		return true;
	}

	template<class T,class UnaryPred>
	T find_if_val(T begin,const T end,const UnaryPred pred)
	{
		while(begin!=end)
		{
			if(pred(begin))
				return begin;
			++begin;
		}
		return end;
	}

	template<class T,class UnaryPred>
	inline bool any_of_val(const T begin,const T end,UnaryPred pred)
	{
		return find_if_val(begin,end,pred)!=end;
	}

	template<class T,class UnaryPred>
	std::ptrdiff_t count_if_val(T begin,const T end,const UnaryPred pred)
	{
		std::ptrdiff_t accu{0};
		while(begin!=end)
		{
			if(pred(begin))
				++accu;
			++begin;
		}
		return accu;
	}

	template<class T,class UnaryFunc>
	UnaryFunc for_each_val(T begin,const T end,const UnaryFunc func)
	{
		while(begin!=end)
		{
			func(begin);
			++begin;
		}
		return func;
	}

	template<class InIter,class UnaryPred,class UnaryFunc>
	void loop_until_none_of(const InIter begin,const InIter end,const UnaryPred pred,const UnaryFunc func)
	{
		for(InIter iter;(iter=find_if(begin,end,pred))!=end;)
			func(*iter);
	}

	template<class InIter,class OutIter,class BinaryOp>
	void multiply(InIter lbegin,const InIter lend,const InIter rbegin,const InIter rend,OutIter des,const BinaryOp op)
	{
		while(lbegin!=lend)
		{
			for(auto begin{rbegin};begin!=rend;++begin,++des)
				*des=op(*lbegin,*begin);
			++lbegin;
		}
	}

	template<class FwdIter,class BinaryPred=std::equal_to<typename std::iterator_traits<FwdIter>::value_type>>
	FwdIter unique_without_sort(FwdIter begin,FwdIter end,const BinaryPred pred=BinaryPred())
	{
		while(begin!=end)
		{
			end=std::remove_if(std::next(begin),end,std::bind(pred,*begin,std::placeholders::_1));
			++begin;
		}
		return end;
	}

	template<class FwdIter,class BinaryPred=std::equal_to<typename std::iterator_traits<FwdIter>::value_type>>
	FwdIter unique_without_sort_thr(const FwdIter begin,const FwdIter end,const std::size_t N,const BinaryPred pred=BinaryPred())
	{
		using namespace std;
		function<void(FwdIter,FwdIter,FwdIter &)> unique_without_sort_thr_{[&,N,pred](const FwdIter begin,const FwdIter end,FwdIter &divide){
			const size_t size{make_unsigned<ptrdiff_t>::type(distance(begin,end))};
			if(N&&N<size)
			{
				divide=end;
				FwdIter lhs_end,rhs_end;
				const auto mid{next(begin,size/2)};
				{
					nThread::CSmartThread lhs{unique_without_sort_thr_,begin,mid,ref(lhs_end)},
						rhs{unique_without_sort_thr_,mid,end,ref(rhs_end)};
				}
				for_each(begin,lhs_end,[&,pred,mid](const typename iterator_traits<FwdIter>::value_type &val){
					rhs_end=std::remove_if(mid,rhs_end,std::bind(pred,val,placeholders::_1));
				});
				divide=std::move(mid,rhs_end,lhs_end);
			}
			else
				divide=unique_without_sort(begin,end,pred);
		}};
		FwdIter retVal;
		unique_without_sort_thr_(begin,end,retVal);
		return retVal;
	}

	template<class FwdIter,class BinaryPred=std::equal_to<typename std::iterator_traits<FwdIter>::value_type>>
	inline FwdIter unique_without_sort_thr(FwdIter begin,FwdIter end,BinaryPred pred=BinaryPred())
	{
		return unique_without_sort_thr(begin,end,std::distance(begin,end)/2,pred);
	}
	//Both of unique_without_sort and unique_without_sort_thr will reorder the input permutation.
}

#endif<commit_msg>add const to pred<commit_after>#ifndef ALGORITHM
#define ALGORITHM
#include<algorithm>	//move
#include<cstddef>
#include<functional>	//bind, placeholders
#include<iterator>
#include<type_traits>	//make_unsigned
#include<utility>	//move
#include"../thread/CSmartThread.hpp"

namespace nAlgorithm
{
	template<class T,class UnaryPred>
	bool all_of_val(T begin,const T end,const UnaryPred pred)
	{
		while(begin!=end)
		{
			if(!pred(begin))
				return false;
			++begin;
		}
		return true;
	}

	template<class T,class UnaryPred>
	T find_if_val(T begin,const T end,const UnaryPred pred)
	{
		while(begin!=end)
		{
			if(pred(begin))
				return begin;
			++begin;
		}
		return end;
	}

	template<class T,class UnaryPred>
	inline bool any_of_val(const T begin,const T end,const UnaryPred pred)
	{
		return find_if_val(begin,end,pred)!=end;
	}

	template<class T,class UnaryPred>
	std::ptrdiff_t count_if_val(T begin,const T end,const UnaryPred pred)
	{
		std::ptrdiff_t accu{0};
		while(begin!=end)
		{
			if(pred(begin))
				++accu;
			++begin;
		}
		return accu;
	}

	template<class T,class UnaryFunc>
	UnaryFunc for_each_val(T begin,const T end,const UnaryFunc func)
	{
		while(begin!=end)
		{
			func(begin);
			++begin;
		}
		return func;
	}

	template<class InIter,class UnaryPred,class UnaryFunc>
	void loop_until_none_of(const InIter begin,const InIter end,const UnaryPred pred,const UnaryFunc func)
	{
		for(InIter iter;(iter=find_if(begin,end,pred))!=end;)
			func(*iter);
	}

	template<class InIter,class OutIter,class BinaryOp>
	void multiply(InIter lbegin,const InIter lend,const InIter rbegin,const InIter rend,OutIter des,const BinaryOp op)
	{
		while(lbegin!=lend)
		{
			for(auto begin{rbegin};begin!=rend;++begin,++des)
				*des=op(*lbegin,*begin);
			++lbegin;
		}
	}

	template<class FwdIter,class BinaryPred=std::equal_to<typename std::iterator_traits<FwdIter>::value_type>>
	FwdIter unique_without_sort(FwdIter begin,FwdIter end,const BinaryPred pred=BinaryPred())
	{
		while(begin!=end)
		{
			end=std::remove_if(std::next(begin),end,std::bind(pred,*begin,std::placeholders::_1));
			++begin;
		}
		return end;
	}

	template<class FwdIter,class BinaryPred=std::equal_to<typename std::iterator_traits<FwdIter>::value_type>>
	FwdIter unique_without_sort_thr(const FwdIter begin,const FwdIter end,const std::size_t N,const BinaryPred pred=BinaryPred())
	{
		using namespace std;
		function<void(FwdIter,FwdIter,FwdIter &)> unique_without_sort_thr_{[&,N,pred](const FwdIter begin,const FwdIter end,FwdIter &divide){
			const size_t size{make_unsigned<ptrdiff_t>::type(distance(begin,end))};
			if(N&&N<size)
			{
				divide=end;
				FwdIter lhs_end,rhs_end;
				const auto mid{next(begin,size/2)};
				{
					nThread::CSmartThread lhs{unique_without_sort_thr_,begin,mid,ref(lhs_end)},
						rhs{unique_without_sort_thr_,mid,end,ref(rhs_end)};
				}
				for_each(begin,lhs_end,[&,pred,mid](const typename iterator_traits<FwdIter>::value_type &val){
					rhs_end=std::remove_if(mid,rhs_end,std::bind(pred,val,placeholders::_1));
				});
				divide=std::move(mid,rhs_end,lhs_end);
			}
			else
				divide=unique_without_sort(begin,end,pred);
		}};
		FwdIter retVal;
		unique_without_sort_thr_(begin,end,retVal);
		return retVal;
	}

	template<class FwdIter,class BinaryPred=std::equal_to<typename std::iterator_traits<FwdIter>::value_type>>
	inline FwdIter unique_without_sort_thr(FwdIter begin,FwdIter end,BinaryPred pred=BinaryPred())
	{
		return unique_without_sort_thr(begin,end,std::distance(begin,end)/2,pred);
	}
	//Both of unique_without_sort and unique_without_sort_thr will reorder the input permutation.
}

#endif<|endoftext|>


<commit_before>/*
    This file is part of Android File Transfer For Linux.
    Copyright (C) 2015  Vladimir Menshakov

    Android File Transfer For Linux is free software: you can redistribute
    it and/or modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    Android File Transfer For Linux is distributed in the hope that it will
    be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Android File Transfer For Linux.
    If not, see <http://www.gnu.org/licenses/>.
 */

#include "mainwindow.h"
#include "utils.h"
#include <QApplication>
#include <QLibraryInfo>
#include <QLocale>
#include <QMessageBox>
#include <QTranslator>

namespace
{
	class Application : public QApplication
	{
	public:
		Application(int &argc, char **argv, int flags = ApplicationFlags):
			QApplication(argc, argv, flags)
		{ }

		virtual bool notify ( QObject * receiver, QEvent * e )
		{
			try {
				return QApplication::notify( receiver, e );
			} catch ( const std::exception& e ) {
				QMessageBox::warning(0, "Error", fromUtf8(e.what()));
				return false;
			}
		}
	};
}

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	QCoreApplication::setApplicationName("mtp-ng-qt");
	QCoreApplication::setOrganizationDomain("whoozle.github.io");
	QCoreApplication::setOrganizationName("whoozle.github.io");

	QTranslator qtTranslator;

	qtTranslator.load("qt_" + QLocale::system().name(),
					QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	a.installTranslator(&qtTranslator);

	QTranslator aTranslator;
	aTranslator.load(":/translations/android-file-transfer-linux_" + QLocale::system().name());
	a.installTranslator(&aTranslator);

	MainWindow w;
	w.show();

	if (!w.started())
		return 1;

	return a.exec();
}
<commit_msg>added missing Q_INIT_RESOURCE<commit_after>/*
    This file is part of Android File Transfer For Linux.
    Copyright (C) 2015  Vladimir Menshakov

    Android File Transfer For Linux is free software: you can redistribute
    it and/or modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    Android File Transfer For Linux is distributed in the hope that it will
    be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Android File Transfer For Linux.
    If not, see <http://www.gnu.org/licenses/>.
 */

#include "mainwindow.h"
#include "utils.h"
#include <QApplication>
#include <QLibraryInfo>
#include <QLocale>
#include <QMessageBox>
#include <QTranslator>

namespace
{
	class Application : public QApplication
	{
	public:
		Application(int &argc, char **argv, int flags = ApplicationFlags):
			QApplication(argc, argv, flags)
		{ }

		virtual bool notify ( QObject * receiver, QEvent * e )
		{
			try {
				return QApplication::notify( receiver, e );
			} catch ( const std::exception& e ) {
				QMessageBox::warning(0, "Error", fromUtf8(e.what()));
				return false;
			}
		}
	};
}

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

	QApplication a(argc, argv);
	QCoreApplication::setApplicationName("mtp-ng-qt");
	QCoreApplication::setOrganizationDomain("whoozle.github.io");
	QCoreApplication::setOrganizationName("whoozle.github.io");

	QTranslator qtTranslator;

	qtTranslator.load("qt_" + QLocale::system().name(),
					QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	a.installTranslator(&qtTranslator);

	QTranslator aTranslator;
	aTranslator.load(":/translations/android-file-transfer-linux_" + QLocale::system().name());
	a.installTranslator(&aTranslator);

	MainWindow w;
	w.show();

	if (!w.started())
		return 1;

	return a.exec();
}
<|endoftext|>


<commit_before>#ifndef RECURSE_REQUEST_HPP
#define RECURSE_REQUEST_HPP

struct Request {
    // tcp request data
    QString data;

    // higher level data
    QHash<QString, QString> header;
    QHash<QString, QVariant> body_parsed;
    QString body, method, proto, url;
};

#endif
<commit_msg>request: add body_length<commit_after>#ifndef RECURSE_REQUEST_HPP
#define RECURSE_REQUEST_HPP

struct Request {
    // tcp request data
    QString data;

    // higher level data
    QHash<QString, QString> header;
    QHash<QString, QVariant> body_parsed;
    QString body, method, proto, url;
    int body_length = 0;
};

#endif
<|endoftext|>


<commit_before>#include "board.hpp"
#include "reversi.hpp"

namespace roadagain
{

Reversi::Reversi() : black_(0), white_(0)
{
    board_ = new Board();
}

Reversi::~Reversi()
{
    delete board_;
}

void Reversi::start()
{
    board_->print();
}

}
<commit_msg>Changed default black and white value from 0 to 2<commit_after>#include "board.hpp"
#include "reversi.hpp"

namespace roadagain
{

Reversi::Reversi() : black_(2), white_(2)
{
    board_ = new Board();
}

Reversi::~Reversi()
{
    delete board_;
}

void Reversi::start()
{
    board_->print();
}

}
<|endoftext|>


<commit_before>/**
 *       \file  well_results_storage.cpp
 *      \brief  Well results storage
 *     \author  Sayfullin Ilshat
 *       \date  28.01.2009
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */

/**
 * @file well_results_storage.cpp
 * @brief well results storage
 * @author Sayfullin Ilshat
 * @date 2009-01-28
 */
#include "stdafx.h"
#include "well_results_storage.h"

namespace blue_sky
  {

  /**
   * @brief constructor
   */
  connection_results::connection_results ()
  {
    d_params.resize (CONN_D_PARAM_COUNT);
    i_params.resize (CONN_I_PARAM_COUNT);
  }

  /**
   * @brief destructor
   */
  connection_results::~connection_results ()
  {}

  void
  connection_results::clear ()
  {
    for (size_t i = 0, cnt = d_params.size (); i < cnt; ++i)
      {
        d_params[i].clear ();
      }

    for (size_t i = 0, cnt = i_params.size (); i < cnt; ++i)
      {
        i_params[i].clear ();
      }
  }

  /**
   * @brief constructor
   */
  well_results::well_results ()
  {
    d_params.resize (WELL_D_PARAM_COUNT);
    i_params.resize (WELL_I_PARAM_COUNT);
  }

  /**
   * @brief destructor
   */
  well_results::~well_results ()
  {}

  void
  well_results::clear ()
  {
    dates.clear ();

    for (size_t i = 0, cnt = d_params.size (); i < cnt; ++i)
      {
        d_params[i].clear ();
      }

    for (size_t i = 0, cnt = i_params.size (); i < cnt; ++i)
      {
        i_params[i].clear ();
      }
  }

  /**
   * @brief constructor
   */
  well_results_storage::well_results_storage (bs_type_ctor_param param /* = NULL */)
  {}
  well_results_storage::well_results_storage (const well_results_storage& src)
      : bs_refcounter (src), objbase (src)
  {
    *this = src;
  }
  /**
   * @brief destructor
   */
  well_results_storage::~well_results_storage ()
  {}

  class well_results;
  class connection_results;

  BLUE_SKY_TYPE_STD_CREATE(well_results_storage)
  BLUE_SKY_TYPE_STD_COPY(well_results_storage)
  BLUE_SKY_TYPE_IMPL_SHORT(well_results_storage, objbase, "well_results_storage")
} //blue_sky

<commit_msg>Edit: Fix link errors on msvc<commit_after>/**
 *       \file  well_results_storage.cpp
 *      \brief  Well results storage
 *     \author  Sayfullin Ilshat
 *       \date  28.01.2009
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */

/**
 * @file well_results_storage.cpp
 * @brief well results storage
 * @author Sayfullin Ilshat
 * @date 2009-01-28
 */
#include "stdafx.h"
#include "well_results_storage.h"
#include "fip_results_storage.h"

namespace blue_sky
  {

  /**
   * @brief constructor
   */
  connection_results::connection_results ()
  {
    d_params.resize (CONN_D_PARAM_COUNT);
    i_params.resize (CONN_I_PARAM_COUNT);
  }

  /**
   * @brief destructor
   */
  connection_results::~connection_results ()
  {}

  void
  connection_results::clear ()
  {
    for (size_t i = 0, cnt = d_params.size (); i < cnt; ++i)
      {
        d_params[i].clear ();
      }

    for (size_t i = 0, cnt = i_params.size (); i < cnt; ++i)
      {
        i_params[i].clear ();
      }
  }

  /**
   * @brief constructor
   */
  well_results::well_results ()
  {
    d_params.resize (WELL_D_PARAM_COUNT);
    i_params.resize (WELL_I_PARAM_COUNT);
  }

  /**
   * @brief destructor
   */
  well_results::~well_results ()
  {}

  void
  well_results::clear ()
  {
    dates.clear ();

    for (size_t i = 0, cnt = d_params.size (); i < cnt; ++i)
      {
        d_params[i].clear ();
      }

    for (size_t i = 0, cnt = i_params.size (); i < cnt; ++i)
      {
        i_params[i].clear ();
      }
  }

  /**
   * @brief constructor
   */
  well_results_storage::well_results_storage (bs_type_ctor_param param /* = NULL */)
  {}
  well_results_storage::well_results_storage (const well_results_storage& src)
      : bs_refcounter (src), objbase (src)
  {
    *this = src;
  }
  /**
   * @brief destructor
   */
  well_results_storage::~well_results_storage ()
  {}

  class well_results;
  class connection_results;

  BLUE_SKY_TYPE_STD_CREATE(well_results_storage)
  BLUE_SKY_TYPE_STD_COPY(well_results_storage)
  BLUE_SKY_TYPE_IMPL_SHORT(well_results_storage, objbase, "well_results_storage")
} //blue_sky

<|endoftext|>


<commit_before>// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "handler/mac/file_limit_annotation.h"

#include <errno.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
#include <sys/types.h>

#include <string>

#include "base/format_macros.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "client/crashpad_info.h"
#include "client/simple_string_dictionary.h"

namespace {

// rv is the return value from sysctl() or sysctlbyname(), and value and size
// are the pointers passed as oldp and oldlenp. If sysctl() failed, the returned
// string will be "E" followed by the error number. If there was a size
// mismatch, the returned string will be "Z" followed by the size indicated by
// sysctl(). Normally, a string representation of *value will be returned.
std::string FormatFromSysctl(int rv, const int* value, const size_t* size) {
  if (rv != 0) {
    return base::StringPrintf("E%d", errno);
  }
  if (*size != sizeof(*value)) {
    return base::StringPrintf("Z%zu", *size);
  }
  return base::StringPrintf("%d", *value);
}

// Returns a string for |limit|, or "inf" if |limit| is RLIM_INFINITY.
std::string StringForRLim(rlim_t limit) {
  if (limit == RLIM_INFINITY) {
    return std::string("inf");
  }

  return base::StringPrintf("%" PRIu64, limit);
}

}  // namespace

namespace crashpad {

void RecordFileLimitAnnotation() {
  CrashpadInfo* crashpad_info = CrashpadInfo::GetCrashpadInfo();
  SimpleStringDictionary* simple_annotations =
      crashpad_info->simple_annotations();
  if (!simple_annotations) {
    simple_annotations = new SimpleStringDictionary();
    crashpad_info->set_simple_annotations(simple_annotations);
  }

  int value;
  size_t size = sizeof(value);
  std::string num_files = FormatFromSysctl(
      sysctlbyname("kern.num_files", &value, &size, nullptr, 0), &value, &size);

  int mib[] = {CTL_KERN, KERN_MAXFILES};
  size = sizeof(value);
  std::string max_files = FormatFromSysctl(
      sysctl(mib, arraysize(mib), &value, &size, nullptr, 0), &value, &size);

  rlimit limit;
  std::string nofile;
  if (getrlimit(RLIMIT_NOFILE, &limit) != 0) {
    nofile = base::StringPrintf("E%d,E%d", errno, errno);
  } else {
    nofile =
        StringForRLim(limit.rlim_cur) + "," + StringForRLim(limit.rlim_max);
  }

  std::string annotation = base::StringPrintf(
      "%s,%s,%s", num_files.c_str(), max_files.c_str(), nofile.c_str());
  simple_annotations->SetKeyValue("file-limits", annotation.c_str());
}

}  // namespace crashpad
<commit_msg>mac handler: Record the number of open files in the handler process<commit_after>// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "handler/mac/file_limit_annotation.h"

#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
#include <sys/types.h>

#include <string>

#include "base/format_macros.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "client/crashpad_info.h"
#include "client/simple_string_dictionary.h"
#include "util/posix/scoped_dir.h"

namespace crashpad {

namespace {

// rv is the return value from sysctl() or sysctlbyname(), and value and size
// are the pointers passed as oldp and oldlenp. If sysctl() failed, the returned
// string will be "E" followed by the error number. If there was a size
// mismatch, the returned string will be "Z" followed by the size indicated by
// sysctl(). Normally, a string representation of *value will be returned.
std::string FormatFromSysctl(int rv, const int* value, const size_t* size) {
  if (rv != 0) {
    return base::StringPrintf("E%d", errno);
  }
  if (*size != sizeof(*value)) {
    return base::StringPrintf("Z%zu", *size);
  }
  return base::StringPrintf("%d", *value);
}

// Counts the number of open file descriptors in the process and returns it as a
// string. This /dev/fd and the value returned will include the open file
// descriptor for that directory. If opendir() fails, the returned string will
// be "E" followed by the error number. If readdir_r() fails, it will be "R"
// followed by the error number.
std::string CountOpenFileDescriptors() {
  DIR* dir = opendir("/dev/fd");
  if (!dir) {
    return base::StringPrintf("E%d", errno);
  }

  ScopedDIR dir_owner(dir);

  dirent entry;
  dirent* result;
  int count = 0;
  while ((errno = readdir_r(dir, &entry, &result)) == 0 && result != nullptr) {
    const char* entry_name = &(*result->d_name);
    if (strcmp(entry_name, ".") == 0 || strcmp(entry_name, "..") == 0) {
      continue;
    }

    ++count;
  }

  if (errno != 0) {
    return base::StringPrintf("R%d", errno);
  }

  return base::StringPrintf("%d", count);
}

// Returns a string for |limit|, or "inf" if |limit| is RLIM_INFINITY.
std::string StringForRLim(rlim_t limit) {
  if (limit == RLIM_INFINITY) {
    return std::string("inf");
  }

  return base::StringPrintf("%" PRIu64, limit);
}

}  // namespace

void RecordFileLimitAnnotation() {
  CrashpadInfo* crashpad_info = CrashpadInfo::GetCrashpadInfo();
  SimpleStringDictionary* simple_annotations =
      crashpad_info->simple_annotations();
  if (!simple_annotations) {
    simple_annotations = new SimpleStringDictionary();
    crashpad_info->set_simple_annotations(simple_annotations);
  }

  int value;
  size_t size = sizeof(value);
  std::string num_files = FormatFromSysctl(
      sysctlbyname("kern.num_files", &value, &size, nullptr, 0), &value, &size);

  int mib[] = {CTL_KERN, KERN_MAXFILES};
  size = sizeof(value);
  std::string max_files = FormatFromSysctl(
      sysctl(mib, arraysize(mib), &value, &size, nullptr, 0), &value, &size);

  std::string open_files = CountOpenFileDescriptors();

  rlimit limit;
  std::string nofile;
  if (getrlimit(RLIMIT_NOFILE, &limit) != 0) {
    nofile = base::StringPrintf("E%d,E%d", errno, errno);
  } else {
    nofile =
        StringForRLim(limit.rlim_cur) + "," + StringForRLim(limit.rlim_max);
  }

  std::string annotation = base::StringPrintf("%s,%s,%s,%s",
                                              num_files.c_str(),
                                              max_files.c_str(),
                                              open_files.c_str(),
                                              nofile.c_str());
  simple_annotations->SetKeyValue("file-limits", annotation.c_str());
}

}  // namespace crashpad
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <breakiterator_th.hxx>
#include <wtt.h>

#include <string.h>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::rtl;

namespace com { namespace sun { namespace star { namespace i18n {

//  ----------------------------------------------------
//  class Breakiterator_th
//  ----------------------------------------------------;
BreakIterator_th::BreakIterator_th()
{
    cBreakIterator = "com.sun.star.i18n.BreakIterator_th";
    wordRule=lineRule=NULL;
}

BreakIterator_th::~BreakIterator_th()
{
}

#define SARA_AM 0x0E33

/*
 * cell composition states
 */

#define ST_COM  1   // Compose the following character with leading char and display in the same cell
#define ST_NXT  2   // display the following character in the next cell
#define ST_NDP  3   // non-display

static const sal_Int16 thaiCompRel[MAX_CT][MAX_CT] = {
    //  C  N  C  L  F  F  F  B  B  B  T  A  A  A  A  A  A
    //  T  O  O  V  V  V  V  V  V  D  O  D  D  D  V  V  V
    //  R  N  N     1  2  3  1  2     N  1  2  3  1  2  3
    //  L     S                       E
    //  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // CTRL 0
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // NON  1
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM   }, // CONS 2
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // LV   3
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // FV1  4
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // FV2  5
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // FV3  6
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // BV1  7
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // BV2  8
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // BD   9
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // TONE 10
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AD1  11
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AD2  12
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AD3  13
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AV1  14
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AV2  15
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_NXT, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT   } // AV3  16

};

const sal_uInt32 is_ST_COM = (1<<CT_CTRL)|(1<<CT_NON)|(1<<CT_CONS)|(1<<CT_TONE);

static sal_uInt16 SAL_CALL getCombState(const sal_Unicode *text, sal_Int32 pos)
{
    sal_uInt16 ch1 = getCharType(text[pos]);
    sal_uInt16 ch2 = getCharType(text[pos+1]);

    if (text[pos+1] == SARA_AM) {
        if ((1 << ch1) & is_ST_COM)
        return  ST_COM;
        else
        ch2 = CT_AD1;
    }

    return thaiCompRel[ch1][ch2];
}

static sal_Int32 SAL_CALL getACell(const sal_Unicode *text, sal_Int32 pos, sal_Int32 len)
{
    sal_uInt32 curr = 1;
    for (; pos + 1 < len && getCombState(text, pos) == ST_COM; curr++, pos++) {}
    return curr;
}

#define is_Thai(c)  (0x0e00 <= c && c <= 0x0e7f) // Unicode definition for Thai

void SAL_CALL BreakIterator_th::makeIndex(const OUString& Text, sal_Int32 nStartPos)
    throw(RuntimeException)
{
    if (Text != cachedText) {
        cachedText = Text;
        if (cellIndexSize < cachedText.getLength()) {
            cellIndexSize = cachedText.getLength();
            free(nextCellIndex);
            free(previousCellIndex);
            nextCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
            previousCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
        }
        // reset nextCell for new Text
        memset(nextCellIndex, 0, cellIndexSize * sizeof(sal_Int32));
    }
    else if (nextCellIndex[nStartPos] > 0 || ! is_Thai(Text[nStartPos]))
        return;

    const sal_Unicode* str = cachedText.getStr();
    sal_Int32 len = cachedText.getLength(), startPos, endPos;

    startPos = nStartPos;
    while (startPos > 0 && is_Thai(str[startPos-1])) startPos--;
    endPos = nStartPos+1;
    while (endPos < len && is_Thai(str[endPos])) endPos++;

    sal_Int32 start, end, pos;
    pos = start = end = startPos;

    while (pos < endPos) {
        end += getACell(str, start, endPos);
        while (pos < end) {
        nextCellIndex[pos] = end;
        previousCellIndex[pos] = start;
        pos++;
        }
        start = end;
    }
}

} } } }

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Do not access nextCellIndex (nor Text) past the end<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <breakiterator_th.hxx>
#include <wtt.h>

#include <string.h>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::rtl;

namespace com { namespace sun { namespace star { namespace i18n {

//  ----------------------------------------------------
//  class Breakiterator_th
//  ----------------------------------------------------;
BreakIterator_th::BreakIterator_th()
{
    cBreakIterator = "com.sun.star.i18n.BreakIterator_th";
    wordRule=lineRule=NULL;
}

BreakIterator_th::~BreakIterator_th()
{
}

#define SARA_AM 0x0E33

/*
 * cell composition states
 */

#define ST_COM  1   // Compose the following character with leading char and display in the same cell
#define ST_NXT  2   // display the following character in the next cell
#define ST_NDP  3   // non-display

static const sal_Int16 thaiCompRel[MAX_CT][MAX_CT] = {
    //  C  N  C  L  F  F  F  B  B  B  T  A  A  A  A  A  A
    //  T  O  O  V  V  V  V  V  V  D  O  D  D  D  V  V  V
    //  R  N  N     1  2  3  1  2     N  1  2  3  1  2  3
    //  L     S                       E
    //  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // CTRL 0
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // NON  1
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM, ST_COM   }, // CONS 2
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // LV   3
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // FV1  4
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // FV2  5
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // FV3  6
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // BV1  7
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // BV2  8
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // BD   9
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // TONE 10
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AD1  11
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AD2  12
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AD3  13
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AV1  14
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT   }, // AV2  15
    {   ST_NDP, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_NXT, ST_COM, ST_NXT, ST_COM, ST_NXT, ST_NXT, ST_NXT, ST_NXT   } // AV3  16

};

const sal_uInt32 is_ST_COM = (1<<CT_CTRL)|(1<<CT_NON)|(1<<CT_CONS)|(1<<CT_TONE);

static sal_uInt16 SAL_CALL getCombState(const sal_Unicode *text, sal_Int32 pos)
{
    sal_uInt16 ch1 = getCharType(text[pos]);
    sal_uInt16 ch2 = getCharType(text[pos+1]);

    if (text[pos+1] == SARA_AM) {
        if ((1 << ch1) & is_ST_COM)
        return  ST_COM;
        else
        ch2 = CT_AD1;
    }

    return thaiCompRel[ch1][ch2];
}

static sal_Int32 SAL_CALL getACell(const sal_Unicode *text, sal_Int32 pos, sal_Int32 len)
{
    sal_uInt32 curr = 1;
    for (; pos + 1 < len && getCombState(text, pos) == ST_COM; curr++, pos++) {}
    return curr;
}

#define is_Thai(c)  (0x0e00 <= c && c <= 0x0e7f) // Unicode definition for Thai

void SAL_CALL BreakIterator_th::makeIndex(const OUString& Text, sal_Int32 nStartPos)
    throw(RuntimeException)
{
    if (Text != cachedText) {
        cachedText = Text;
        if (cellIndexSize < cachedText.getLength()) {
            cellIndexSize = cachedText.getLength();
            free(nextCellIndex);
            free(previousCellIndex);
            nextCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
            previousCellIndex = (sal_Int32*) calloc(cellIndexSize, sizeof(sal_Int32));
        }
        // reset nextCell for new Text
        memset(nextCellIndex, 0, cellIndexSize * sizeof(sal_Int32));
    }
    else if (nStartPos >= Text.getLength() || nextCellIndex[nStartPos] > 0
             || !is_Thai(Text[nStartPos]))
        return;

    const sal_Unicode* str = cachedText.getStr();
    sal_Int32 len = cachedText.getLength(), startPos, endPos;

    startPos = nStartPos;
    while (startPos > 0 && is_Thai(str[startPos-1])) startPos--;
    endPos = nStartPos+1;
    while (endPos < len && is_Thai(str[endPos])) endPos++;

    sal_Int32 start, end, pos;
    pos = start = end = startPos;

    while (pos < endPos) {
        end += getACell(str, start, endPos);
        while (pos < end) {
        nextCellIndex[pos] = end;
        previousCellIndex[pos] = start;
        pos++;
        }
        start = end;
    }
}

} } } }

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "game_over_screen.h"

#include <stdio.h>
#include <string.h>

#include <boost/format.hpp>

#include "audio.h"
#include "input.h"
#include "game_screen.h"
#include "graphics.h"
#include "title_screen.h"

namespace {
  const int interval = 250;
}

void GameOverScreen::init(Graphics& graphics) {
  backdrop.reset(new Backdrop(graphics, "paper"));
  text.reset(new Text(graphics));

  icon_whale.reset(new Sprite(graphics, "ui", 0, 48, 32, 16));
  icon_fish.reset(new Sprite(graphics, "ui", 32, 48, 16, 16));

  phase = TITLE;
  fish_drawn = whales_drawn = 0;
  place = 99;
  initials_pos = 0;
  timer = 0;

  FILE* fd = fopen("content/scores.txt", "r");
  if (fd) {
    for (int i = 0; i < 10; ++i) {
      char initials[4];
      int score;

      fscanf(fd, "%s%u\n", &initials, &score);

      if (damage > score && place > 10) {
        fprintf(stderr, "Congrats, %u place\n", i);
        place = i;
        strcpy(top_scores[i].initials, "___");
        top_scores[i].score = damage;
        ++i;
      }

      // bounds check in case bottom score was bumped
      if (i < 10) {
        strcpy(top_scores[i].initials, initials);
        top_scores[i].score = score;
      }
    }
    fclose(fd);
  } else {
    fprintf(stderr, "Unable to read high score file\n");
  }
}

bool GameOverScreen::update(Input& input, Audio& audio, Graphics&, int elapsed) {
  timer -= elapsed;

  if (timer < 0) {
    timer += interval;

    if (phase == KILLS) {
      if (whales > 0) {
        whales_drawn++;
        audio.play_sample("kill");
        if (--whales == 0) timer += 2 * interval;
      } else if (fish > 0) {
        fish_drawn++;
        audio.play_sample("kill");
        if (--fish == 0) timer += 2 * interval;
      } else {
        next_phase(audio);
      }
    } else if (phase != SCORES) {
      next_phase(audio);
    }
  }

  if (phase == OPTIONS) {

    if (input.key_pressed(SDLK_q)) {
      choice = REPLAY;
      return false;
    } else if (input.key_pressed(SDLK_e)) {
      choice = MENU;
      return false;
    } else if (input.key_pressed(SDLK_ESCAPE)) {
      choice = QUIT;
      return false;
    }

  } else if (phase == KILLS) {
    if (input.any_pressed()) {
      whales_drawn += whales;
      fish_drawn += fish;
      whales = fish = 0;
      next_phase(audio);
    }

  } else if (phase == SCORES) {

    if (place < 10 && initials_pos < 3) {
      // horrible hack because of how I handle input :(
      for (int i = SDLK_a; i < SDLK_z; ++i) {
        if (input.key_pressed(i)) {
          top_scores[place].initials[initials_pos] = i - SDLK_a + 'A';
          ++initials_pos;
          break;
        }
      }

      if (initials_pos == 3) {
        FILE* fd = fopen("content/scores.txt", "w");
        if (fd) {
          for (int i = 0; i < 10; ++i) {
            fprintf(fd, "%3s %u\n", top_scores[i].initials, top_scores[i].score);
          }
          fclose(fd);
        } else {
          fprintf(stderr, "Unable to write scores to file\n");
        }
      }
    } else {
      next_phase(audio);
    }
  }

  return true;
}

void GameOverScreen::draw(Graphics& graphics) {
  backdrop->draw(graphics);

  if (phase >= TITLE) text->draw(graphics, 48, 80, "Environmental Impact Report");

  int y = 112;

  if (phase >= KILLS) {
    text->draw(graphics, 48, y, "Animals Killed:");
    y += 16;
    int x = 48;

    for (int i = 0; i < whales_drawn; ++i) {
      icon_whale->draw(graphics, x, y);

      x += 32;
      if (x > 544) {
        x = 48;
        y += 16;
      }
    }

    for (int i = 0; i < fish_drawn; ++i) {
      icon_fish->draw(graphics, x, y);

      x += 16;
      if (x > 560) {
        x = 48;
        y += 16;
      }
    }

    y += 32;
  }

  if (phase >= DAMAGE) {
    text->draw(graphics, 48, y, boost::str(boost::format("Total Damage: $% 9u") % damage));
    y += 32;
  }

  if (phase >= SCORES) {
    text->draw(graphics, 48, y, "Most Wanted:");
    for (int i = 0; i < 5; ++i) {
      text->draw(graphics,  48, y + 16 * i + 16, boost::str(boost::format("%2u. %3s   $%9u") % (i + 1) % top_scores[i].initials % top_scores[i].score));
      text->draw(graphics, 320, y + 16 * i + 16, boost::str(boost::format("%2u. %3s   $%9u") % (i + 6) % top_scores[i + 5].initials % top_scores[i + 5].score));

    }

    y += 112;

    if (place < 10) {
      text->draw(graphics, 48, y,
          "Congratulations, you are one of the most horrible people we\n"
          "have ever encountered.  Please acknowledge receipt of this\n"
          "report by entering your initials above.\n"
      );

      y += 64;
    }

  }

  if (phase >= OPTIONS) {
    text->draw(graphics, 48, y, "Q: Play again     E: Main Menu     Esc: Quit");
  }
}

Screen* GameOverScreen::next_screen() {
  switch (choice) {
    case REPLAY: return new GameScreen();
    case MENU: return new TitleScreen();
    case QUIT: return NULL;
  }
}

std::string GameOverScreen::get_music_track() {
  return "";
}

void GameOverScreen::set_scores(int total_damage, int whales_killed, int fish_killed) {
  damage = total_damage;
  whales = whales_killed;
  fish = fish_killed;
}

void GameOverScreen::next_phase(Audio& audio) {
  if (phase == OPTIONS) return;

  phase = static_cast<Phase>(phase + 1);
  timer += interval * 2;
  audio.play_sample("boom");
}
<commit_msg>Fix scanf handling<commit_after>#include "game_over_screen.h"

#include <stdio.h>
#include <string.h>

#include <boost/format.hpp>

#include "audio.h"
#include "input.h"
#include "game_screen.h"
#include "graphics.h"
#include "title_screen.h"

namespace {
  const int interval = 250;
}

void GameOverScreen::init(Graphics& graphics) {
  backdrop.reset(new Backdrop(graphics, "paper"));
  text.reset(new Text(graphics));

  icon_whale.reset(new Sprite(graphics, "ui", 0, 48, 32, 16));
  icon_fish.reset(new Sprite(graphics, "ui", 32, 48, 16, 16));

  phase = TITLE;
  fish_drawn = whales_drawn = 0;
  place = 99;
  initials_pos = 0;
  timer = 0;

  FILE* fd = fopen("content/scores.txt", "r");
  if (fd) {
    for (int i = 0; i < 10; ++i) {
      char initials[4];
      int score;

      int count = fscanf(fd, "%3s%u\n", initials, &score);
      if (count < 2) break;

      if (damage > score && place > 10) {
        fprintf(stderr, "Congrats, %u place\n", i);
        place = i;
        strcpy(top_scores[i].initials, "___");
        top_scores[i].score = damage;
        ++i;
      }

      // bounds check in case bottom score was bumped
      if (i < 10) {
        strcpy(top_scores[i].initials, initials);
        top_scores[i].score = score;
      }
    }
    fclose(fd);
  } else {
    fprintf(stderr, "Unable to read high score file\n");
  }
}

bool GameOverScreen::update(Input& input, Audio& audio, Graphics&, int elapsed) {
  timer -= elapsed;

  if (timer < 0) {
    timer += interval;

    if (phase == KILLS) {
      if (whales > 0) {
        whales_drawn++;
        audio.play_sample("kill");
        if (--whales == 0) timer += 2 * interval;
      } else if (fish > 0) {
        fish_drawn++;
        audio.play_sample("kill");
        if (--fish == 0) timer += 2 * interval;
      } else {
        next_phase(audio);
      }
    } else if (phase != SCORES) {
      next_phase(audio);
    }
  }

  if (phase == OPTIONS) {

    if (input.key_pressed(SDLK_q)) {
      choice = REPLAY;
      return false;
    } else if (input.key_pressed(SDLK_e)) {
      choice = MENU;
      return false;
    } else if (input.key_pressed(SDLK_ESCAPE)) {
      choice = QUIT;
      return false;
    }

  } else if (phase == KILLS) {
    if (input.any_pressed()) {
      whales_drawn += whales;
      fish_drawn += fish;
      whales = fish = 0;
      next_phase(audio);
    }

  } else if (phase == SCORES) {

    if (place < 10 && initials_pos < 3) {
      // horrible hack because of how I handle input :(
      for (int i = SDLK_a; i < SDLK_z; ++i) {
        if (input.key_pressed(i)) {
          top_scores[place].initials[initials_pos] = i - SDLK_a + 'A';
          ++initials_pos;
          break;
        }
      }

      if (initials_pos == 3) {
        FILE* fd = fopen("content/scores.txt", "w");
        if (fd) {
          for (int i = 0; i < 10; ++i) {
            fprintf(fd, "%3s %u\n", top_scores[i].initials, top_scores[i].score);
          }
          fclose(fd);
        } else {
          fprintf(stderr, "Unable to write scores to file\n");
        }
      }
    } else {
      next_phase(audio);
    }
  }

  return true;
}

void GameOverScreen::draw(Graphics& graphics) {
  backdrop->draw(graphics);

  if (phase >= TITLE) text->draw(graphics, 48, 80, "Environmental Impact Report");

  int y = 112;

  if (phase >= KILLS) {
    text->draw(graphics, 48, y, "Animals Killed:");
    y += 16;
    int x = 48;

    for (int i = 0; i < whales_drawn; ++i) {
      icon_whale->draw(graphics, x, y);

      x += 32;
      if (x > 544) {
        x = 48;
        y += 16;
      }
    }

    for (int i = 0; i < fish_drawn; ++i) {
      icon_fish->draw(graphics, x, y);

      x += 16;
      if (x > 560) {
        x = 48;
        y += 16;
      }
    }

    y += 32;
  }

  if (phase >= DAMAGE) {
    text->draw(graphics, 48, y, boost::str(boost::format("Total Damage: $% 9u") % damage));
    y += 32;
  }

  if (phase >= SCORES) {
    text->draw(graphics, 48, y, "Most Wanted:");
    for (int i = 0; i < 5; ++i) {
      text->draw(graphics,  48, y + 16 * i + 16, boost::str(boost::format("%2u. %3s   $%9u") % (i + 1) % top_scores[i].initials % top_scores[i].score));
      text->draw(graphics, 320, y + 16 * i + 16, boost::str(boost::format("%2u. %3s   $%9u") % (i + 6) % top_scores[i + 5].initials % top_scores[i + 5].score));

    }

    y += 112;

    if (place < 10) {
      text->draw(graphics, 48, y,
          "Congratulations, you are one of the most horrible people we\n"
          "have ever encountered.  Please acknowledge receipt of this\n"
          "report by entering your initials above.\n"
      );

      y += 64;
    }

  }

  if (phase >= OPTIONS) {
    text->draw(graphics, 48, y, "Q: Play again     E: Main Menu     Esc: Quit");
  }
}

Screen* GameOverScreen::next_screen() {
  switch (choice) {
    case REPLAY: return new GameScreen();
    case MENU: return new TitleScreen();
    case QUIT: return NULL;
  }
}

std::string GameOverScreen::get_music_track() {
  return "";
}

void GameOverScreen::set_scores(int total_damage, int whales_killed, int fish_killed) {
  damage = total_damage;
  whales = whales_killed;
  fish = fish_killed;
}

void GameOverScreen::next_phase(Audio& audio) {
  if (phase == OPTIONS) return;

  phase = static_cast<Phase>(phase + 1);
  timer += interval * 2;
  audio.play_sample("boom");
}
<|endoftext|>


<commit_before>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geom/Coordinate.h>
#include <geos/platform.h> // for ISNAN

#include <sstream>
#include <string>

#ifndef GEOS_INLINE
# include <geos/geom/Coordinate.inl>
#endif

using namespace std;

namespace geos {
namespace geom { // geos::geom

Coordinate Coordinate::nullCoord=Coordinate(DoubleNotANumber,DoubleNotANumber,DoubleNotANumber);

Coordinate&
Coordinate::getNull()
{
	return nullCoord;
}

string
Coordinate::toString() const
{
	ostringstream s;
	s<<*this;
	return s.str();
}

std::ostream& operator<< (std::ostream& os, const Coordinate& c)
{
	if ( ISNAN(c.z) )
	{
		os << c.x << " " << c.y;
	} else {
		os << c.x << " " << c.y << " " << c.z;
	}
	return os;
}

} // namespace geos::geom
} // namespace geos

<commit_msg>Use 18 significant digits for TopologyException point coordinates<commit_after>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geom/Coordinate.h>
#include <geos/platform.h> // for ISNAN

#include <sstream>
#include <string>
#include <iomanip>

#ifndef GEOS_INLINE
# include <geos/geom/Coordinate.inl>
#endif

using namespace std;

namespace geos {
namespace geom { // geos::geom

Coordinate Coordinate::nullCoord=Coordinate(DoubleNotANumber,DoubleNotANumber,DoubleNotANumber);

Coordinate&
Coordinate::getNull()
{
	return nullCoord;
}

string
Coordinate::toString() const
{
	ostringstream s;
	s << std::setprecision(17) << *this;
	return s.str();
}

std::ostream& operator<< (std::ostream& os, const Coordinate& c)
{
	if ( ISNAN(c.z) )
	{
		os << c.x << " " << c.y;
	} else {
		os << c.x << " " << c.y << " " << c.z;
	}
	return os;
}

} // namespace geos::geom
} // namespace geos

<|endoftext|>


<commit_before>// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
// RUN:   -fdebug-prefix-map=%S=/SOURCE_ROOT %s -emit-llvm -o - | FileCheck %s

template <typename T> void b(T) {}
void c() {
  // CHECK: !DISubprogram(name: "b<(lambda at
  // CHECK-SAME:          /SOURCE_ROOT/debug-prefix-map-lambda.cpp
  // CHECK-SAME:          [[@LINE+1]]:{{[0-9]+}})>"
  b([]{});
}
<commit_msg>Reapply fix from r348062 to fix test on Windows.<commit_after>// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
// RUN:   -fdebug-prefix-map=%S=/SOURCE_ROOT %s -emit-llvm -o - | FileCheck %s

template <typename T> void b(T) {}
void c() {
  // CHECK: !DISubprogram(name: "b<(lambda at
  // CHECK-SAME:          SOURCE_ROOT
  // CHECK-SAME:          [[@LINE+1]]:{{[0-9]+}})>"
  b([]{});
}
<|endoftext|>