<commit_before>//
//  API.cpp
//  miniSQL
//
//  Created by Kael on 11/3/14.
//  Copyright (c) 2014 Xinyuan Lu. All rights reserved.
//

// v2.0, see comment in "APT.h"

#include "API.h"

Recordinfo API::dealCmd(sqlcommand& sql){
	// 使用get方法更好，这里先直接调用public
	switch(sql.sqlType){
		case 0:
		return select(sql);
		break;
		case 1:
		return del(sql);
		break;
		case 2:
		return insert(sql);
		break;
		case 3:
		return createTable(sql);
		break;
		case 4:
		return createIndex(sql);
		break;
		case 5:
		return dropTable(sql);
		break;
		case 6:
		return dropIndex(sql);
		break;
	}
	return Recordinfo();
}

int API::AttrCount(std::string tablename){
	return catalogmanager->AttrCount(tablename);
}
bool API::TableExists(std::string tablename){
	return catalogmanager->TableExists(tablename);
}
bool API::IndexExists(std::string indexname){
	return catalogmanager->IndexExists(indexname);
}
bool API::AttrExists(std::string attrname,std::string tablename){
	return catalogmanager->AttrExists(attrname, tablename);
}

// 以下所有的都需要错误输入的检查？
Recordinfo API::select(sqlcommand& sql){
	// 先到catalog查看是否有index
	// 如果有就用，然后作intersection
	// 如果没有，直接交给record？
	// 可以减少数据传递的overhead
	bool flag=false;
    std::vector<std::vector<std::string> >::iterator conditioni;
	Recordinfo result;

	int IndexAttrType=0x7fff;

	for(conditioni=sql.conditions.begin(); conditioni<sql.conditions.end(); conditioni++){
		flag=catalogmanager->hasIndex(sql.tablename, (*conditioni).at(0));
		if(flag) {
			IndexAttrType=catalogmanager->getAttrType(sql.tablename, (*conditioni).at(0));
			break;
		}
	}

    // 需要商量
    Table table=catalogmanager->getTable(sql.tablename);

	if(!flag) {
		std::vector<slot> slots;
		result=recordmanager->Select_Record(sql, table, false, slots);
	}
	else{
		Value *v=NULL;
		switch(IndexAttrType){
			case 0:
			v=new Value(IndexAttrType, std::stoi((*conditioni).at(2)));
			break;
			case 1:
			v=new Value(IndexAttrType, (*conditioni).at(2));
			break;
			case -1:
			v=new Value(IndexAttrType, std::stof((*conditioni).at(2)));
			break;
		}
		IndexManager *indexmanager=new IndexManager();

        std::vector<slot> s;
		if((*conditioni).at(1)=="<") s=indexmanager->_FindSmall((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<=") s=indexmanager->_FindSmallEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">") s=indexmanager->_FindBigger((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">=") s=indexmanager->_FindBiggerEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<>") s=indexmanager->_FindNotEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="=") s.push_back(indexmanager->select((*conditioni).at(0), *v));
        if(s.size()==0 || (s.size()==1 && s[0].block_id==-1)){
            delete v;
            return Recordinfo(false, "Cannot find the record!", Result(), 0);
        }
        result=recordmanager->Select_Record(sql, table, true, s);
		// 然后开始剩下的暴力获取
        sql.conditions.erase(conditioni);
        Recordinfo result2=recordmanager->Select_Record(sql, table, false, s);
        // and
        result.AND(result2);
		delete v;
	}
    return result;
}

Recordinfo API::del(sqlcommand& sql){
    bool flag=false;
    //	int n=-1;	// 记录第几个是index
    std::vector<std::vector<std::string> >::iterator conditioni;
    Recordinfo result;

    int IndexAttrType=0x7fff;

    for(conditioni=sql.conditions.begin(); conditioni<sql.conditions.end(); conditioni++){
        flag=catalogmanager->hasIndex(sql.tablename, (*conditioni).at(0));
        if(flag) {
            IndexAttrType=catalogmanager->getAttrType(sql.tablename, (*conditioni).at(0));
            break;
        }
    }

    // 需要商量
    Table table=catalogmanager->getTable(sql.tablename);

    if(!flag) {
        std::vector<slot> slots;
        result=recordmanager->Delete_Record(sql, table, false, slots);
    }
    else{
        Value *v=NULL;
        switch(IndexAttrType){
            case 0:v=new Value(IndexAttrType, std::stoi((*conditioni).at(2)));break;
            case 1:v=new Value(IndexAttrType, (*conditioni).at(2));break;
            case -1:v=new Value(IndexAttrType, std::stof((*conditioni).at(2)));break;
        }

        std::vector<slot> s;
        if((*conditioni).at(1)=="<") s=indexmanager->_FindSmall((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<=") s=indexmanager->_FindSmallEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">") s=indexmanager->_FindBigger((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">=") s=indexmanager->_FindBiggerEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<>") s=indexmanager->_FindNotEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="=") s.push_back(indexmanager->select((*conditioni).at(0), *v));
        if(s.size()==0 || (s.size()==1 && s[0].block_id==-1)){
            delete v;
            return Recordinfo(false, "Cannot find the record!", Result(), 0);
        }
        result=recordmanager->Delete_Record(sql, table, true, s);
        // 然后开始剩下的暴力获取
        sql.conditions.erase(conditioni);
        Recordinfo result2=recordmanager->Select_Record(sql, table, false, s);
        // and
        result.AND(result2);
        delete v;
    }
    return result;
}

Recordinfo API::insert(sqlcommand& sql){
	// 为什么insert也要有sqlcommand????
    // 插入index

    Recordinfo result;
    Table table=catalogmanager->getTable(sql.tablename);
    int block_id;
    int record_id;

    // check primary
    std::string primarykey=catalogmanager->pkOnTable(sql.tablename);
    if(primarykey=="Table not found in CatalogBlocks!"){
        result=Recordinfo(false, primarykey, Result(), 0);
        return result;
    }
    else{
        for(int i=0; i<sql.colValue.size(); i++){
            if(catalogmanager->isUnique(sql.tablename, i) || catalogmanager->isPK(sql.tablename, i)){
                std::string attrname=catalogmanager->getAttrName(sql.tablename, i);
                // 如果有索引就用索引，并且更新索引
                if(catalogmanager->hasIndex(sql.tablename, attrname)){
                    std::string indexname=catalogmanager->getIndexName(sql.tablename, attrname);
                    int AttrType=catalogmanager->getAttrType(sql.tablename, primarykey);
                    Value *v=NULL;
                    switch(AttrType){
                        case 0:v=new Value(AttrType, std::stoi((sql.colValue).at(i)));break;
                        case 1:v=new Value(AttrType, (sql.colValue).at(i));break;
                        case -1:v=new Value(AttrType, std::stof(sql.colValue.at(i)));break;
                    }
                    slot s=indexmanager->select(indexname, *v);
                    if(s.block_id!=-1){
                        Recordinfo result=Recordinfo(false, "The unique key value has existed!", Result(), 0);
                        delete v;
                        return result;
                    }
                    delete v;
                }
                // 没有索引直接查询
                sqlcommand tempsql=sql;
                tempsql.sqlType=0;
                tempsql.conditions={{attrname, "=", sql.colValue[i]}};
                tempsql.selectInfo={"*"};
                Recordinfo r=recordmanager->Select_Record(tempsql, table, 0, std::vector<slot>());
                if(r.successful){
                    result=Recordinfo(false, "The unique key value has existed!", Result(), 0);
                    return result;
                }
            }
        }

        result=recordmanager->Insert_Record(sql, table, block_id, record_id);
        //插入索引
        slot s=slot(block_id, record_id);
        for(int i=0; i<sql.colValue.size(); i++){
            std::string attrname=catalogmanager->getAttrName(sql.tablename, i);
            if(catalogmanager->hasIndex(sql.tablename, attrname)){
                std::string indexname=catalogmanager->getIndexName(sql.tablename, attrname);
                int AttrType=catalogmanager->getAttrType(sql.tablename, primarykey);
                Value *v=NULL;
                switch(AttrType){
                    case 0:v=new Value(AttrType, std::stoi((sql.colValue).at(i)));break;
                    case 1:v=new Value(AttrType, (sql.colValue).at(i));break;
                    case -1:v=new Value(AttrType, std::stof(sql.colValue.at(i)));break;
                }
                indexmanager->_insert(indexname, *v, s);
            }
        }
        // 解决可能的返回错误？
        return result;
    }
}

Recordinfo API::createTable(sqlcommand& sql){
    catalogmanager->insertTable(sql);
    std::string pk;
    std::string tablename=sql.createTableInfo[0].at(0);
    if((pk=catalogmanager->pkOnTable(tablename))!="No primary key on this table!"){
        // 可以创建空的index吧？
        indexmanager->CreateIndex(tablename+"$"+pk, catalogmanager->getAttrType(tablename, pk), std::vector<Value>(0), std::vector<slot>(0));

        sqlcommand tempsql=sqlcommand();
        tempsql.sqlType=4;
        tempsql.indexname=tablename+"$"+pk;
        tempsql.setCreateIndexInfo(tablename, pk);
        catalogmanager->insertIndex(tempsql);
    }
    return Recordinfo(); // further improve
}

Recordinfo API::createIndex(sqlcommand& sql){
	std::string tablename=sql.createIndexInfo[1];
    std::string indexname=sql.createIndexInfo[0];
    int attrtype=catalogmanager->getAttrType(tablename, sql.createIndexInfo[2]);
    indexmanager->CreateIndex(sql.indexname, attrtype, std::vector<Value>(), std::vector<slot>());

    catalogmanager->insertIndex(sql);
        return Recordinfo(); // further improve
}

// turn to Catalog find all index and
// drop index
// dropCatalog
// drop all records
Recordinfo API::dropTable(sqlcommand& sql){
    std::string tablename=sql.tablename;

    for(int i=0; i<catalogmanager->AttrCount(tablename); i++){
        std::string attrname=catalogmanager->getAttrName(tablename, i);
        if(catalogmanager->hasIndex(tablename, attrname)){
            indexmanager->DropIndex(catalogmanager->getIndexName(tablename, attrname));
            catalogmanager->dropIndex(catalogmanager->getIndexName(tablename, attrname));
        }
    }
    catalogmanager->dropTable(sql.tablename);
        return Recordinfo(); // further improve
}

Recordinfo API::dropIndex(sqlcommand& sql){
    catalogmanager->dropIndex(sql.indexname);
    indexmanager->DropIndex(sql.indexname);
        return Recordinfo(); // further improve
    // catalog
}<commit_msg>update API<commit_after>//
//  API.cpp
//  miniSQL
//
//  Created by Kael on 11/3/14.
//  Copyright (c) 2014 Xinyuan Lu. All rights reserved.
//

// v2.0, see comment in "APT.h"

#include "API.h"

Recordinfo API::dealCmd(sqlcommand& sql){
	// 使用get方法更好，这里先直接调用public
	switch(sql.sqlType){
		case 0:
		return select(sql);
		break;
		case 1:
		return del(sql);
		break;
		case 2:
		return insert(sql);
		break;
		case 3:
		return createTable(sql);
		break;
		case 4:
		return createIndex(sql);
		break;
		case 5:
		return dropTable(sql);
		break;
		case 6:
		return dropIndex(sql);
		break;
	}
	return Recordinfo();
}

int API::AttrCount(std::string tablename){
	return catalogmanager->AttrCount(tablename);
}
bool API::TableExists(std::string tablename){
	return catalogmanager->TableExists(tablename);
}
bool API::IndexExists(std::string indexname){
	return catalogmanager->IndexExists(indexname);
}
bool API::AttrExists(std::string attrname,std::string tablename){
	return catalogmanager->AttrExists(attrname, tablename);
}

// 以下所有的都需要错误输入的检查？
Recordinfo API::select(sqlcommand& sql){
	// 先到catalog查看是否有index
	// 如果有就用，然后作intersection
	// 如果没有，直接交给record？
	// 可以减少数据传递的overhead
	bool flag=false;
    std::vector<std::vector<std::string> >::iterator conditioni;
	Recordinfo result;

	int IndexAttrType=0x7fff;

	for(conditioni=sql.conditions.begin(); conditioni<sql.conditions.end(); conditioni++){
		flag=catalogmanager->hasIndex(sql.tablename, (*conditioni).at(0));
		if(flag) {
			IndexAttrType=catalogmanager->getAttrType(sql.tablename, (*conditioni).at(0));
			break;
		}
	}

    // 需要商量
    Table table=catalogmanager->getTable(sql.tablename);

	if(!flag) {
		std::vector<slot> slots;
		result=recordmanager->Select_Record(sql, table, false, slots);
	}
	else{
		Value *v=NULL;
		switch(IndexAttrType){
			case 0:
			v=new Value(IndexAttrType, std::stoi((*conditioni).at(2)));
			break;
			case 1:
			v=new Value(IndexAttrType, (*conditioni).at(2));
			break;
			case -1:
			v=new Value(IndexAttrType, std::stof((*conditioni).at(2)));
			break;
		}
		IndexManager *indexmanager=new IndexManager();

        std::vector<slot> s;
		if((*conditioni).at(1)=="<") s=indexmanager->_FindSmall((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<=") s=indexmanager->_FindSmallEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">") s=indexmanager->_FindBigger((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">=") s=indexmanager->_FindBiggerEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<>") s=indexmanager->_FindNotEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="=") s.push_back(indexmanager->select((*conditioni).at(0), *v));
        if(s.size()==0 || (s.size()==1 && s[0].block_id==-1)){
            delete v;
            return Recordinfo(false, "Cannot find the record!", Result(), 0);
        }
        result=recordmanager->Select_Record(sql, table, true, s);
		// 然后开始剩下的暴力获取
        sql.conditions.erase(conditioni);
        Recordinfo result2=recordmanager->Select_Record(sql, table, false, s);
        // and
        result.AND(result2);
		delete v;
	}
    return result;
}

Recordinfo API::del(sqlcommand& sql){
    bool flag=false;
    //	int n=-1;	// 记录第几个是index
    std::vector<std::vector<std::string> >::iterator conditioni;
    Recordinfo result;

    int IndexAttrType=0x7fff;

    for(conditioni=sql.conditions.begin(); conditioni<sql.conditions.end(); conditioni++){
        flag=catalogmanager->hasIndex(sql.tablename, (*conditioni).at(0));
        if(flag) {
            IndexAttrType=catalogmanager->getAttrType(sql.tablename, (*conditioni).at(0));
            break;
        }
    }

    // 需要商量
    Table table=catalogmanager->getTable(sql.tablename);

    if(!flag) {
        std::vector<slot> slots;
        result=recordmanager->Delete_Record(sql, table, false, slots);
    }
    else{
        Value *v=NULL;
        switch(IndexAttrType){
            case 0:v=new Value(IndexAttrType, std::stoi((*conditioni).at(2)));break;
            case 1:v=new Value(IndexAttrType, (*conditioni).at(2));break;
            case -1:v=new Value(IndexAttrType, std::stof((*conditioni).at(2)));break;
        }

        std::vector<slot> s;
        if((*conditioni).at(1)=="<") s=indexmanager->_FindSmall((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<=") s=indexmanager->_FindSmallEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">") s=indexmanager->_FindBigger((*conditioni).at(0), *v);
        else if((*conditioni).at(1)==">=") s=indexmanager->_FindBiggerEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="<>") s=indexmanager->_FindNotEqual((*conditioni).at(0), *v);
        else if((*conditioni).at(1)=="=") s.push_back(indexmanager->select((*conditioni).at(0), *v));
        if(s.size()==0 || (s.size()==1 && s[0].block_id==-1)){
            delete v;
            return Recordinfo(false, "Cannot find the record!", Result(), 0);
        }
        result=recordmanager->Delete_Record(sql, table, true, s);
        // 然后开始剩下的暴力获取
        sql.conditions.erase(conditioni);
        Recordinfo result2=recordmanager->Select_Record(sql, table, false, s);
        // and
        result.AND(result2);
        delete v;
    }
    return result;
}

Recordinfo API::insert(sqlcommand& sql){
	// 为什么insert也要有sqlcommand????
    // 插入index

    Recordinfo result;
    Table table=catalogmanager->getTable(sql.tablename);
    int block_id;
    int record_id;

    // check primary
    std::string primarykey=catalogmanager->pkOnTable(sql.tablename);
    if(primarykey=="Table not found in CatalogBlocks!"){
        result=Recordinfo(false, primarykey, Result(), 0);
        return result;
    }
    else{
        for(int i=0; i<sql.colValue.size(); i++){
            if(catalogmanager->isUnique(sql.tablename, i) || catalogmanager->isPK(sql.tablename, i)){
                std::string attrname=catalogmanager->getAttrName(sql.tablename, i);
                // 如果有索引就用索引，并且更新索引
                if(catalogmanager->hasIndex(sql.tablename, attrname)){
                    std::string indexname=catalogmanager->getIndexName(sql.tablename, attrname);
                    int AttrType=catalogmanager->getAttrType(sql.tablename, primarykey);
                    Value *v=NULL;
                    switch(AttrType){
                        case 0:v=new Value(AttrType, std::stoi((sql.colValue).at(i)));break;
                        case 1:v=new Value(AttrType, (sql.colValue).at(i));break;
                        case -1:v=new Value(AttrType, std::stof(sql.colValue.at(i)));break;
                    }
                    slot s=indexmanager->select(indexname, *v);
                    if(s.block_id!=-1){
                        Recordinfo result=Recordinfo(false, "The unique key value has existed!", Result(), 0);
                        delete v;
                        return result;
                    }
                    delete v;
                }
                // 没有索引直接查询
                sqlcommand tempsql=sql;
                tempsql.sqlType=0;
                tempsql.conditions={{attrname, "=", sql.colValue[i]}};
                tempsql.selectInfo={"*"};
                Recordinfo r=recordmanager->Select_Record(tempsql, table, 0, std::vector<slot>());
                if(r.successful){
                    result=Recordinfo(false, "The unique key value has existed!", Result(), 0);
                    return result;
                }
            }
        }

        result=recordmanager->Insert_Record(sql, table, block_id, record_id);
        //插入索引
        slot s=slot(block_id, record_id);
        for(int i=0; i<sql.colValue.size(); i++){
            std::string attrname=catalogmanager->getAttrName(sql.tablename, i);
            if(catalogmanager->hasIndex(sql.tablename, attrname)){
                std::string indexname=catalogmanager->getIndexName(sql.tablename, attrname);
                int AttrType=catalogmanager->getAttrType(sql.tablename, primarykey);
                Value *v=NULL;
                switch(AttrType){
                    case 0:v=new Value(AttrType, std::stoi((sql.colValue).at(i)));break;
                    case 1:v=new Value(AttrType, (sql.colValue).at(i));break;
                    case -1:v=new Value(AttrType, std::stof(sql.colValue.at(i)));break;
                }
                indexmanager->_insert(indexname, *v, s);
            }
        }
        // 解决可能的返回错误？
        return result;
    }
}

Recordinfo API::createTable(sqlcommand& sql){
    catalogmanager->insertTable(sql);
    std::string pk;
    std::string tablename=sql.createTableInfo[0].at(0);
    if((pk=catalogmanager->pkOnTable(tablename))!="No primary key on this table!"){
        // 可以创建空的index吧？
        indexmanager->CreateIndex(tablename+"$"+pk, catalogmanager->getAttrType(tablename, pk), std::vector<Value>(0), std::vector<slot>(0));

        sqlcommand tempsql=sqlcommand();
        tempsql.sqlType=4;
        tempsql.indexname=tablename+"$"+pk;
        tempsql.setCreateIndexInfo(tablename, pk);
        catalogmanager->insertIndex(tempsql);
    }
    return Recordinfo(); // further improve
}

Recordinfo API::createIndex(sqlcommand& sql){
	std::string tablename=sql.createIndexInfo[1];
    std::string indexname=sql.createIndexInfo[0];
    int attrtype=catalogmanager->getAttrType(tablename, sql.createIndexInfo[2]);
    catalogmanager->insertIndex(sql);
    indexmanager->CreateIndex(sql.indexname, attrtype, std::vector<Value>(), std::vector<slot>());
    // insert all records to index
    sqlcommand tempsql=sqlcommand();
    tempsql.sqlType=0;
    tempsql.selectInfo=std::vector<std::string>();
    tempsql.selectInfo.push_back(sql.createIndexInfo[2]);
    tempsql.tablename=tablename;
    tempsql.conditions=std::vector<std::vector<std::string> >();
    Table temptable=catalogmanager->getTable(tablename);
    std::vector<slot> tempslot=std::vector<slot>();
    Recordinfo result=recordmanager->Select_Record(tempsql, temptable, 0, tempslot);
    for(int i=0;i<tempslot.size();i++){
        Value v;
        switch(attrtype){
            case 0:v=Value(attrtype, std::stoi(result.res.rows[i].cols[0]));break;
            case 1:v=Value(attrtype, result.res.rows[i].cols[0]);break;
            case -1:v=Value(attrtype, std::stof(result.res.rows[i].cols[0]));break;
        }
        indexmanager->_insert(indexname, v, tempslot[i]);
    }

    return Recordinfo(); // further improve
}

// turn to Catalog find all index and
// drop index
// dropCatalog
// drop all records
Recordinfo API::dropTable(sqlcommand& sql){
    std::string tablename=sql.tablename;

    // delete all records
    sqlcommand tempsql=sqlcommand();
    tempsql.sqlType=1;
    tempsql.conditions=std::vector<std::vector<std::string> >();
    tempsql.tablename=sql.tablename;
    Table temptable=catalogmanager->getTable(sql.tablename);
    recordmanager->Delete_Record(tempsql, temptable, 0, std::vector<slot>());

    // delete all indexes
    for(int i=0; i<catalogmanager->AttrCount(tablename); i++){
        std::string attrname=catalogmanager->getAttrName(tablename, i);
        if(catalogmanager->hasIndex(tablename, attrname)){
            indexmanager->DropIndex(catalogmanager->getIndexName(tablename, attrname));
            catalogmanager->dropIndex(catalogmanager->getIndexName(tablename, attrname));
        }
    }
    // delete catalog
    catalogmanager->dropTable(sql.tablename);
        return Recordinfo(); // further improve
}

Recordinfo API::dropIndex(sqlcommand& sql){
    catalogmanager->dropIndex(sql.indexname);
    indexmanager->DropIndex(sql.indexname);
        return Recordinfo(); // further improve
    // catalog
}<|endoftext|>


<commit_before>class TrieNode {
public:
    bool isKey;
    TrieNode* children[26];
    TrieNode(): isKey(false) {
        memset(children, NULL, sizeof(TrieNode*) * 26);
    }
};

class WordDictionary {
public:
    WordDictionary() {
        root = new TrieNode();
    }

    // Adds a word into the data structure.
    void addWord(string word) {
        TrieNode* run = root;
        for (char c : word) {
            if (!(run -> children[c - 'a']))
                run -> children[c - 'a'] = new TrieNode();
            run = run -> children[c - 'a'];
        }
        run -> isKey = true;
    }

    // Returns if the word is in the data structure. A word could
    // contain the dot character '.' to represent any one letter.
    bool search(string word) {
        return query(word.c_str(), root);
    }

private:
    TrieNode* root;

    bool query(const char* word, TrieNode* node) {
        TrieNode* run = node;
        for (int i = 0; word[i]; i++) {
            if (run && word[i] != '.')
                run = run -> children[word[i] - 'a'];
            else if (run && word[i] == '.') {
                TrieNode* tmp = run;
                for (int j = 0; j < 26; j++) {
                    run = tmp -> children[j];
                    if (query(word + i + 1, run))
                        return true;
                }
            }
            else break;
        }
        return run && run -> isKey;
    }
};

// Your WordDictionary object will be instantiated and called as such:
// WordDictionary wordDictionary;
// wordDictionary.addWord("word");
// wordDictionary.search("pattern");<commit_msg>Update 211.cpp<commit_after>/*
 * Trie
 *
 */
class TrieNode {
public:
    bool isKey;
    TrieNode* children[26];
    TrieNode(): isKey(false) {
        memset(children, NULL, sizeof(TrieNode*) * 26);
    }
};

class WordDictionary {
public:
    WordDictionary() {
        root = new TrieNode();
    }

    // Adds a word into the data structure.
    void addWord(string word) {
        TrieNode* run = root;
        for (char c : word) {
            if (!(run -> children[c - 'a']))
                run -> children[c - 'a'] = new TrieNode();
            run = run -> children[c - 'a'];
        }
        run -> isKey = true;
    }

    // Returns if the word is in the data structure. A word could
    // contain the dot character '.' to represent any one letter.
    bool search(string word) {
        return query(word.c_str(), root);
    }

private:
    TrieNode* root;

    bool query(const char* word, TrieNode* node) {
        TrieNode* run = node;
        for (int i = 0; word[i]; i++) {
            if (run && word[i] != '.')
                run = run -> children[word[i] - 'a'];
            else if (run && word[i] == '.') {
                TrieNode* tmp = run;
                for (int j = 0; j < 26; j++) {
                    run = tmp -> children[j];
                    if (query(word + i + 1, run))
                        return true;
                }
            }
            else break;
        }
        return run && run -> isKey;
    }
};

// Conclusion:
//
//
//

<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Michael Egli
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * \author    Michael Egli
 * \copyright Michael Egli
 * \date      11-Jul-2015
 *
 * \file cpptime.cpp
 *
 * See the description in the header file for for more information.
 *
 */

// Includes
#include <thread>
#include <mutex>
#include <condition_variable>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>
#include <unordered_map>
#include "cpptime.h"

namespace
{
using scoped_m = std::unique_lock<std::mutex>;

// Prototypes
CppTime::timer_id next_id();

// Use to terminate the timer thread.
bool done = false;
// The index variable used to construct the timer_id.
uint64_t cur_id = 0;

// Locking & Co
std::mutex m;
std::condition_variable cond;
std::thread worker;

// The event structure that holds the information about a timer.
struct Event {
	CppTime::timer_id id;
	CppTime::timestamp start;
	CppTime::duration period;
	CppTime::handler_t handler;
	bool valid;
	Event()
	    : id(0),
	      start(CppTime::duration::zero()),
	      period(CppTime::duration::zero()),
	      handler(nullptr),
	      valid(false)
	{
	}
	template <typename Func>
	Event(CppTime::timer_id id, CppTime::timestamp start, CppTime::duration period, Func &&handler)
	    : id(id), start(start), period(period), handler(std::forward<Func>(handler)), valid(true)
	{
	}
	Event(Event &&r) noexcept : id(r.id),
	                            start(r.start),
	                            period(r.period),
	                            handler(std::move(r.handler)),
	                            valid(r.valid)
	{
	}
	Event &operator=(Event &&ev) noexcept
	{
		if(this != &ev) {
			id = ev.id;
			start = ev.start;
			period = ev.period;
			handler = std::move(ev.handler);
			valid = ev.valid;
		}
		return *this;
	}
	Event(const Event &r) = delete;
	Event &operator=(const Event &r) = delete;
};

// A time event structure that holds the next timeout and a reference to its
// Event struct.
struct Time_event {
	CppTime::timestamp next;
	CppTime::timer_id ref;
};

inline bool operator<(const Time_event &l, const Time_event &r)
{
	return l.next < r.next;
}

// The vector that holds all active events.
std::vector<Event> events;
// Sorted queue that has the next timeout at its top.
std::priority_queue<Time_event> time_events;

// A list of ids to be re-used. If possible, ids are used from this pool.
std::stack<CppTime::timer_id> free_ids;

// Returns the next free id. First, we check the free ids before creating a new
// one.
CppTime::timer_id next_id()
{
	if(free_ids.empty()) {
		return cur_id++;
	}
	CppTime::timer_id id = free_ids.top();
	free_ids.pop();
	return id;
}

// The thread main entry points. This is an endless loop until the `done` flag
// is set to false.
// TODO cleanup code to make it more readable (less if-else blocks).
void run()
{
	scoped_m lock(m);

	while(!done) {

		if(time_events.empty()) {
			// Wait for work
			cond.wait(lock);
		} else {
			auto te = time_events.top();
			if(CppTime::clock::now() >= te.next) {

				// Remove time event
				time_events.pop();
				Event &ev = events[te.ref];

				if(!ev.valid) {
					// Return the id if the event is no longer valid.
					free_ids.push(te.ref);
				} else {

					// Invoke the handler
					lock.unlock();
					ev.handler(te.ref);
					lock.lock();

					if(!ev.valid) {
						// The callback removed the event.
						free_ids.push(te.ref);
					} else {
						if(ev.period.count() > 0) {
							te.next += ev.period;
							time_events.push(te);
						} else {
							ev.valid = false;
							free_ids.push(te.ref);
						}
					}
				}
			} else {
				cond.wait_until(lock, te.next);
			}
		}
	}
}

} // end anonymous namespace

namespace CppTime
{

void start(size_t expected)
{
	scoped_m lock(m);
	done = false;
	if(expected > 0) {
		events.resize(expected);
	}
	worker = std::thread(&run);
}

void stop()
{
	scoped_m lock(m);
	done = true;
	events.clear();
	while(!time_events.empty()) {
		time_events.pop();
	}
	cond.notify_all();
	lock.unlock();
	worker.join();
}

timer_id add(const timestamp &when, handler_t &&handler, const duration &period)
{
	scoped_m lock(m);
	timer_id id = next_id();
	Event e(id, when, period, std::move(handler));
	if(events.size() <= id) {
		events.resize(id + 1);
	}
	events.insert(events.begin() + id, std::move(e));
	time_events.push(Time_event{e.start, e.id});
	cond.notify_all();
	return e.id;
}

bool remove(timer_id id)
{
	scoped_m lock(m);
	if(events.size() < id) {
		return false;
	}
	events[id].valid = false;
	return true;
}

} // end namespace CppTime
<commit_msg>Do not use the value from the moved object for the timer_id.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Michael Egli
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * \author    Michael Egli
 * \copyright Michael Egli
 * \date      11-Jul-2015
 *
 * \file cpptime.cpp
 *
 * See the description in the header file for for more information.
 *
 */

// Includes
#include <thread>
#include <mutex>
#include <condition_variable>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>
#include <unordered_map>
#include "cpptime.h"

namespace
{
using scoped_m = std::unique_lock<std::mutex>;

// Prototypes
CppTime::timer_id next_id();

// Use to terminate the timer thread.
bool done = false;
// The index variable used to construct the timer_id.
uint64_t cur_id = 0;

// Locking & Co
std::mutex m;
std::condition_variable cond;
std::thread worker;

// The event structure that holds the information about a timer.
struct Event {
	CppTime::timer_id id;
	CppTime::timestamp start;
	CppTime::duration period;
	CppTime::handler_t handler;
	bool valid;
	Event()
	    : id(0),
	      start(CppTime::duration::zero()),
	      period(CppTime::duration::zero()),
	      handler(nullptr),
	      valid(false)
	{
	}
	template <typename Func>
	Event(CppTime::timer_id id, CppTime::timestamp start, CppTime::duration period, Func &&handler)
	    : id(id), start(start), period(period), handler(std::forward<Func>(handler)), valid(true)
	{
	}
	Event(Event &&r) noexcept : id(r.id),
	                            start(r.start),
	                            period(r.period),
	                            handler(std::move(r.handler)),
	                            valid(r.valid)
	{
	}
	Event &operator=(Event &&ev) noexcept
	{
		if(this != &ev) {
			id = ev.id;
			start = ev.start;
			period = ev.period;
			handler = std::move(ev.handler);
			valid = ev.valid;
		}
		return *this;
	}
	Event(const Event &r) = delete;
	Event &operator=(const Event &r) = delete;
};

// A time event structure that holds the next timeout and a reference to its
// Event struct.
struct Time_event {
	CppTime::timestamp next;
	CppTime::timer_id ref;
};

inline bool operator<(const Time_event &l, const Time_event &r)
{
	return l.next < r.next;
}

// The vector that holds all active events.
std::vector<Event> events;
// Sorted queue that has the next timeout at its top.
std::priority_queue<Time_event> time_events;

// A list of ids to be re-used. If possible, ids are used from this pool.
std::stack<CppTime::timer_id> free_ids;

// Returns the next free id. First, we check the free ids before creating a new
// one.
CppTime::timer_id next_id()
{
	if(free_ids.empty()) {
		return cur_id++;
	}
	CppTime::timer_id id = free_ids.top();
	free_ids.pop();
	return id;
}

// The thread main entry points. This is an endless loop until the `done` flag
// is set to false.
// TODO cleanup code to make it more readable (less if-else blocks).
void run()
{
	scoped_m lock(m);

	while(!done) {

		if(time_events.empty()) {
			// Wait for work
			cond.wait(lock);
		} else {
			auto te = time_events.top();
			if(CppTime::clock::now() >= te.next) {

				// Remove time event
				time_events.pop();
				Event &ev = events[te.ref];

				if(!ev.valid) {
					// Return the id if the event is no longer valid.
					free_ids.push(te.ref);
				} else {

					// Invoke the handler
					lock.unlock();
					ev.handler(te.ref);
					lock.lock();

					if(!ev.valid) {
						// The callback removed the event.
						free_ids.push(te.ref);
					} else {
						if(ev.period.count() > 0) {
							te.next += ev.period;
							time_events.push(te);
						} else {
							ev.valid = false;
							free_ids.push(te.ref);
						}
					}
				}
			} else {
				cond.wait_until(lock, te.next);
			}
		}
	}
}

} // end anonymous namespace

namespace CppTime
{

void start(size_t expected)
{
	scoped_m lock(m);
	done = false;
	if(expected > 0) {
		events.resize(expected);
	}
	worker = std::thread(&run);
}

void stop()
{
	scoped_m lock(m);
	done = true;
	events.clear();
	while(!time_events.empty()) {
		time_events.pop();
	}
	cond.notify_all();
	lock.unlock();
	worker.join();
}

timer_id add(const timestamp &when, handler_t &&handler, const duration &period)
{
	scoped_m lock(m);
	timer_id id = next_id();
	Event e(id, when, period, std::move(handler));
	if(events.size() <= id) {
		events.resize(id + 1);
	}
	events.insert(events.begin() + id, std::move(e));
	time_events.push(Time_event{e.start, id});
	cond.notify_all();
	return id;
}

bool remove(timer_id id)
{
	scoped_m lock(m);
	if(events.size() < id) {
		return false;
	}
	events[id].valid = false;
	return true;
}

} // end namespace CppTime
<|endoftext|>


<commit_before>#pragma once

#include <cstddef>
#include <iostream>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

namespace Traits
{
   /**
   * @brief P.F.M
   *
   * @see N3911
   */
   template<class...>
   using void_t = void;

   /**
   * @brief Strips constness and volatility from rvalues.
   */
   template<typename Type>
   using unqualified_t = std::remove_cv_t<std::remove_reference_t<Type>>;

   /**
   * Base case for the testing of STD compatible container types.
   */
   template<
      typename /*Type*/,
      typename = void
   >
   struct is_printable_as_container : std::false_type
   {
   };

   /**
   * @brief Specialization to ensure that Standard Library compatible containers that have
   * `begin()`, `end()`, and `empty()` member functions, as well as the `value_type` and
   * `iterator` typedefs are treated as printable containers.
   */
   template<typename Type>
   struct is_printable_as_container<
      Type,
      void_t<
         decltype(std::declval<Type&>().begin()),
         decltype(std::declval<Type&>().end()),
         decltype(std::declval<Type&>().empty()),
         typename Type::value_type,
         typename Type::iterator
      >
   > : public std::true_type
   {
   };

   /**
   * @brief Specialization to treat std::pair<...> as a printable container type.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct is_printable_as_container<std::pair<FirstType, SecondType>> : public std::true_type
   {
   };

   /**
   * @brief Specialization to treat arrays as printable container types.
   */
   template<
      typename ArrayType,
      std::size_t ArraySize
   >
   struct is_printable_as_container<ArrayType[ArraySize]> : public std::true_type
   {
   };

   /**
   * @brief Narrow character array specialization in order to ensure that we print character arrays
   * as string and not as delimiter containers.
   */
   template<std::size_t ArraySize>
   struct is_printable_as_container<char[ArraySize]> : public std::false_type
   {
   };

   /**
   * @brief Wide character array specialization in order to ensure that we print character arrays
   * as string and not as delimiter containers.
   */
   template<std::size_t ArraySize>
   struct is_printable_as_container<wchar_t[ArraySize]> : public std::false_type
   {
   };

   /**
   * @brief String specialization in order to ensure that we treat strings as nothing more than strings.
   */
   template<
      typename CharacterType,
      typename TraitsType,
      typename AllocatorType
   >
   struct is_printable_as_container<
      std::basic_string<
      CharacterType,
         TraitsType,
         AllocatorType
      >
   > : public std::false_type
   {
   };

   /**
   * @brief Helper variable template.
   */
   template<typename Type>
   constexpr bool is_printable_as_container_v = is_printable_as_container<Type>::value;
}

namespace Printer
{
   /**
   * Convenience struct to neatly wrap up all the additional characters we'll need in order to
   * print out the containers.
   */
   template<typename DelimiterType>
   struct delimiter_values
   {
      using type = DelimiterType;

      const type* prefix;
      const type* delimiter;
      const type* postfix;
   };

   /**
   *
   */
   template<
      typename /*ContainerType*/,
      typename DelimiterType
   >
   struct delimiters
   {
      using type = delimiter_values<DelimiterType>;

      static const type values;
   };

   /**
   * Default narrow delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, char>
   {
      using type = delimiter_values<char>;

      static constexpr type values = { "[", ", ", "]" };
   };

   /**
   * Default wide delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, wchar_t>
   {
      using type = delimiter_values<wchar_t>;

      static constexpr type values = { L"[", L", ", L"]" };
   };

   /**
   * Narrow character specialization for std::set<...>.
   */
   template<
      typename Type,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<Type, ComparatorType, AllocatorType>, char>
   {
      static constexpr delimiter_values<char> values = { "{", ", ", "}" };
   };

   /**
   * Wide character specialization for std::set<...>.
   */
   template<
      typename Type,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<Type, ComparatorType, AllocatorType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"{", L", ", L"}" };
   };

   /**
   * Narrow character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, char>
   {
      static constexpr delimiter_values<char> values = { "(", ", ", ")" };
   };

   /**
   * Wide character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"(", L", ", L")" };
   };

   /**
   * Narrow character specialization for std::tuple<...>.
   */
   template<typename... Types>
   struct delimiters<std::tuple<Types...>, char>
   {
      static constexpr delimiter_values<char> values = { "<", ", ", ">" };
   };

   /**
   * Wide character specialization for std::tuple<...>.
   */
   template<typename... Types>
   struct delimiters<std::tuple<Types...>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"<", L", ", L">" };
   };

   ///**
   //* @brief Base specialization for std::tuple<...>.
   //*/
   //template<
   //   typename ContainerType,
   //   typename TupleType,
   //   typename CharacterType,
   //   typename TraitsType
   //>
   //void PrintingHelper(
   //   std::basic_ostream<CharacterType, TraitsType>& stream,
   //   const std::tuple<TupleType>& container)
   //{
   //   stream << std::get<0>(container);
   //}

   ///**
   //* @brief Recursive specialization for std::tuple<...>.
   //*/
   //template<
   //   typename FirstTupleType,
   //   typename... RemainingTupleTypes,
   //   typename CharacterType,
   //   typename TraitsType
   //>
   //void PrintingHelper(
   //   std::basic_ostream<CharacterType, TraitsType>& stream,
   //   const std::tuple<FirstTupleType, RemainingTupleTypes...>& container)
   //{
   //   static constexpr auto delimiters =
   //      Printer::delimiters<std::tuple<...>, CharacterType>::values;

   //   stream << std::get<0>(container) << delimiters.delimiter;
   //   PrintingHelper(stream, container);
   //}

   /**
   * see http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777
   */
   template<
      typename CharacterType,
      typename TraitsType,
      typename Tuple,
      std::size_t... IndexSequence
   >
   void print_tuple_impl(
      std::basic_ostream<CharacterType, TraitsType>& stream,
      const Tuple& tuple,
      std::index_sequence<IndexSequence...>)
   {
      static constexpr auto delimiters =
         Printer::delimiters<std::tuple<...>, CharacterType>::values;

      using swallow = int[]; // guarantees left to right order

      (void) swallow {
         0,
         (void (stream
            << (IndexSequence == 0 ? "" : delimiters.delimiter)
            << std::get<IndexSequence>(tuple)), 0)...
      };
   }

   /**
   * @brief Printing specialization suitable for most container types.
   */
   template<
      typename ContainerType,
      typename CharacterType,
      typename TraitsType
   >
   void PrintingHelper(
      std::basic_ostream<CharacterType, TraitsType>& stream,
      const ContainerType& container)
   {
      static constexpr auto delimiters = Printer::delimiters<ContainerType, CharacterType>::values;

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

      auto begin = std::begin(container);
      stream << delimiters.prefix << *begin;
      std::advance(begin, 1);

      std::for_each(begin, std::end(container),
         [&stream] (const auto& value)
      {
         stream << delimiters.delimiter << value;
      });

      stream << delimiters.postfix;
   }

   /**
   * @brief Printing specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType,
      typename CharacterType,
      typename TraitsType
   >
   void PrintingHelper(
      std::basic_ostream<CharacterType, TraitsType>& stream,
      const std::pair<FirstType, SecondType>& container)
   {
      static constexpr auto delimiters =
         Printer::delimiters<
            Traits::unqualified_t<decltype(container)>,
            CharacterType
         >::values;

      stream
         << delimiters.prefix
         << container.first
         << delimiters.delimiter
         << container.second
         << delimiters.postfix;
   }

   /**
   * @brief Main class that will print out the container with the help of various templated
   * helper functions.
   */
   template<
      typename ContainerType,
      typename CharacterType,
      typename TraitsType
   >
   class ContainerPrinter
   {
   public:
      ContainerPrinter(const ContainerType& container)
         : m_container{ container }
      {
      }

      inline void PrintTo(std::basic_ostream<CharacterType, TraitsType>& stream) const
      {
         PrintingHelper(stream, m_container);
      }

   private:
      const ContainerType& m_container;
   };
}

/**
* @brief Overload of the stream output operator for compatible containers.
*/
template<
   typename ContainerType,
   typename CharacterType,
   typename TraitsType,
   typename = std::enable_if_t<Traits::is_printable_as_container_v<ContainerType>>
>
auto& operator<<(
   std::basic_ostream<CharacterType, TraitsType>& stream,
   const ContainerType& container)
{
   Printer::ContainerPrinter<ContainerType, CharacterType, TraitsType>(container).PrintTo(stream);

   return stream;
}
<commit_msg>Got std::tuple<...> Printing Working<commit_after>#pragma once

#include <cstddef>
#include <iostream>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

namespace Traits
{
   /**
   * @brief P.F.M
   *
   * @see N3911
   */
   template<class...>
   using void_t = void;

   /**
   * @brief Strips constness and volatility from rvalues.
   */
   template<typename Type>
   using unqualified_t = std::remove_cv_t<std::remove_reference_t<Type>>;

   /**
   * Base case for the testing of STD compatible container types.
   */
   template<
      typename /*Type*/,
      typename = void
   >
   struct is_printable_as_container : std::false_type
   {
   };

   /**
   * @brief Specialization to ensure that Standard Library compatible containers that have
   * `begin()`, `end()`, and `empty()` member functions, as well as the `value_type` and
   * `iterator` typedefs are treated as printable containers.
   */
   template<typename Type>
   struct is_printable_as_container<
      Type,
      void_t<
         decltype(std::declval<Type&>().begin()),
         decltype(std::declval<Type&>().end()),
         decltype(std::declval<Type&>().empty()),
         typename Type::value_type,
         typename Type::iterator
      >
   > : public std::true_type
   {
   };

   /**
   * @brief Specialization to treat std::pair<...> as a printable container type.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct is_printable_as_container<std::pair<FirstType, SecondType>> : public std::true_type
   {
   };

   /**
   * @brief Specialization to treat std::tuple<...> as a printable container type.
   */
   template<typename... DataTypes>
   struct is_printable_as_container<std::tuple<DataTypes...>> : public std::true_type
   {
   };

   /**
   * @brief Specialization to treat arrays as printable container types.
   */
   template<
      typename ArrayType,
      std::size_t ArraySize
   >
   struct is_printable_as_container<ArrayType[ArraySize]> : public std::true_type
   {
   };

   /**
   * @brief Narrow character array specialization in order to ensure that we print character arrays
   * as string and not as delimiter containers.
   */
   template<std::size_t ArraySize>
   struct is_printable_as_container<char[ArraySize]> : public std::false_type
   {
   };

   /**
   * @brief Wide character array specialization in order to ensure that we print character arrays
   * as string and not as delimiter containers.
   */
   template<std::size_t ArraySize>
   struct is_printable_as_container<wchar_t[ArraySize]> : public std::false_type
   {
   };

   /**
   * @brief String specialization in order to ensure that we treat strings as nothing more than strings.
   */
   template<
      typename CharacterType,
      typename TraitsType,
      typename AllocatorType
   >
   struct is_printable_as_container<
      std::basic_string<
      CharacterType,
         TraitsType,
         AllocatorType
      >
   > : public std::false_type
   {
   };

   /**
   * @brief Helper variable template.
   */
   template<typename Type>
   constexpr bool is_printable_as_container_v = is_printable_as_container<Type>::value;
}

namespace Printer
{
   /**
   * Convenience struct to neatly wrap up all the additional characters we'll need in order to
   * print out the containers.
   */
   template<typename DelimiterType>
   struct delimiter_values
   {
      using type = DelimiterType;

      const type* prefix;
      const type* delimiter;
      const type* postfix;
   };

   /**
   *
   */
   template<
      typename /*ContainerType*/,
      typename DelimiterType
   >
   struct delimiters
   {
      using type = delimiter_values<DelimiterType>;

      static const type values;
   };

   /**
   * Default narrow delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, char>
   {
      using type = delimiter_values<char>;

      static constexpr type values = { "[", ", ", "]" };
   };

   /**
   * Default wide delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, wchar_t>
   {
      using type = delimiter_values<wchar_t>;

      static constexpr type values = { L"[", L", ", L"]" };
   };

   /**
   * Narrow character specialization for std::set<...>.
   */
   template<
      typename Type,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<Type, ComparatorType, AllocatorType>, char>
   {
      static constexpr delimiter_values<char> values = { "{", ", ", "}" };
   };

   /**
   * Wide character specialization for std::set<...>.
   */
   template<
      typename Type,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<Type, ComparatorType, AllocatorType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"{", L", ", L"}" };
   };

   /**
   * Narrow character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, char>
   {
      static constexpr delimiter_values<char> values = { "(", ", ", ")" };
   };

   /**
   * Wide character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"(", L", ", L")" };
   };

   /**
   * Narrow character specialization for std::tuple<...>.
   */
   template<typename... Types>
   struct delimiters<std::tuple<Types...>, char>
   {
      static constexpr delimiter_values<char> values = { "<", ", ", ">" };
   };

   /**
   * Wide character specialization for std::tuple<...>.
   */
   template<typename... Types>
   struct delimiters<std::tuple<Types...>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"<", L", ", L">" };
   };

   /**
   * @brief Helper template to unpack and print tuple arguments.
   */
   template<
      typename TupleType,
      std::size_t N,
      typename... Args
   >
   struct TuplePrinter
   {
      template<
         typename CharacterType,
         typename TraitsType,
         typename DelimiterValues
      >
      static void Print(
         std::basic_ostream<CharacterType, TraitsType>& stream,
         const TupleType& container,
         const DelimiterValues& delimiters)
      {
         TuplePrinter<TupleType, N - 1>::Print(stream, container, delimiters);

         stream
            << delimiters.delimiter
            << std::get<N - 1>(container);
      }
   };

   /**
   * @brief Helper template to unpack and print tuple arguments.
   */
   template<typename TupleType>
   struct TuplePrinter<TupleType, 1>
   {
      template<
         typename CharacterType,
         typename TraitsType,
         typename DelimiterValues
      >
      static void Print(
         std::basic_ostream<CharacterType, TraitsType>& stream,
         const TupleType& tuple,
         const DelimiterValues& delimiters)
      {
         stream << std::get<0>(tuple);
      }
   };

   /**
   * @brief Recursive specialization for std::tuple<...>.
   *
   * @see http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat
   */
   template<
      typename CharacterType,
      typename TraitsType,
      typename... Args
   >
   void PrintingHelper(
      std::basic_ostream<CharacterType, TraitsType>& stream,
      const std::tuple<Args...>& container)
   {
      static constexpr auto delimiters =
         Printer::delimiters<Traits::unqualified_t<decltype(container)>, CharacterType>::values;

      stream << delimiters.prefix;
      TuplePrinter<decltype(container), sizeof...(Args)>::Print(stream, container, delimiters);
      stream << delimiters.postfix;
   }

   /**
   * @brief Printing specialization suitable for most container types.
   */
   template<
      typename ContainerType,
      typename CharacterType,
      typename TraitsType
   >
   void PrintingHelper(
      std::basic_ostream<CharacterType, TraitsType>& stream,
      const ContainerType& container)
   {
      static constexpr auto delimiters = Printer::delimiters<ContainerType, CharacterType>::values;

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

      auto begin = std::begin(container);
      stream << delimiters.prefix << *begin;
      std::advance(begin, 1);

      std::for_each(begin, std::end(container),
         [&stream] (const auto& value)
      {
         stream << delimiters.delimiter << value;
      });

      stream << delimiters.postfix;
   }

   /**
   * @brief Printing specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType,
      typename CharacterType,
      typename TraitsType
   >
   void PrintingHelper(
      std::basic_ostream<CharacterType, TraitsType>& stream,
      const std::pair<FirstType, SecondType>& container)
   {
      static constexpr auto delimiters =
         Printer::delimiters<
            Traits::unqualified_t<decltype(container)>,
            CharacterType
         >::values;

      stream
         << delimiters.prefix
         << container.first
         << delimiters.delimiter
         << container.second
         << delimiters.postfix;
   }

   /**
   * @brief Main class that will print out the container with the help of various templated
   * helper functions.
   */
   template<
      typename ContainerType,
      typename CharacterType,
      typename TraitsType
   >
   class ContainerPrinter
   {
   public:
      ContainerPrinter(const ContainerType& container)
         : m_container{ container }
      {
      }

      inline void PrintTo(std::basic_ostream<CharacterType, TraitsType>& stream) const
      {
         PrintingHelper(stream, m_container);
      }

   private:
      const ContainerType& m_container;
   };
}

/**
* @brief Overload of the stream output operator for compatible containers.
*/
template<
   typename ContainerType,
   typename CharacterType,
   typename TraitsType,
   typename = std::enable_if_t<Traits::is_printable_as_container_v<ContainerType>>
>
auto& operator<<(
   std::basic_ostream<CharacterType, TraitsType>& stream,
   const ContainerType& container)
{
   Printer::ContainerPrinter<ContainerType, CharacterType, TraitsType>(container).PrintTo(stream);

   return stream;
}
<|endoftext|>


<commit_before>
#include <gloperate/painter/CameraCollisionCapability.h>

#include <limits>

#include <glm/gtc/matrix_transform.hpp>

#include <glbinding/gl/enum.h>
#include <glbinding/gl/functions.h>
#include <glbinding/gl/bitfield.h>
#include <glbinding/gl/types.h>

#include <globjects/Framebuffer.h>

using namespace gl;

namespace gloperate
{

CameraCollisionCapability::CameraCollisionCapability()
: m_fbo(nullptr)
, m_size(1024)
, m_samplingSize(1)
{

}

CameraCollisionCapability::~CameraCollisionCapability()
{

}

void CameraCollisionCapability::setCollisionFBO(globjects::ref_ptr<globjects::Framebuffer> collisionFBO, size_t texSize)
{
    m_fbo = collisionFBO;
    m_size = texSize;
}

void CameraCollisionCapability::setSamplingSize(size_t samplingSize)
{
    m_samplingSize = samplingSize;
}

float CameraCollisionCapability::getDistance(const glm::vec3 &dir) const
{
    if(!m_fbo)
    {
        return std::numeric_limits<float>::max();
    }

    float xAbs = std::abs(dir.x);
    float yAbs = std::abs(dir.y);
    float zAbs = std::abs(dir.z);
    float main, u, v;
    GLenum face;

    if(xAbs == 0 && yAbs == 0 && zAbs == 0)
    {
        return std::numeric_limits<float>::max();
    }

    //Find the correct axis to sample
    if(xAbs > yAbs && xAbs > zAbs)
    {
        face = GL_COLOR_ATTACHMENT0;
        main = dir.x; u = -dir.z; v = -dir.y;
    } else if(yAbs > zAbs)
    {
        face = GL_COLOR_ATTACHMENT2;
        main = dir.y; u = dir.x; v = dir.z;
    } else
    {
        face = GL_COLOR_ATTACHMENT4;
        main = dir.z; u = -dir.x; v = -dir.y;
    }

    //Find the correct orientation on this axis
    face = face + static_cast<int>(std::signbit(main));

    //Sample the coordinates
    glm::vec2 uv{u/std::abs(main), v/std::abs(main)};
    glm::ivec2 i_uv = uv * static_cast<float>(m_size/2)+static_cast<float>(m_size/2);
    std::vector<glm::vec3> buf(m_samplingSize*m_samplingSize);

    m_fbo->bind();

    std::array<GLint,4> sampleRange{i_uv.x,i_uv.y,m_samplingSize,m_samplingSize};
    m_fbo->readPixels(face, sampleRange,GL_RGB,GL_FLOAT,buf.data());

    m_fbo->unbind();

    return buf[0].x;
}

} // namespace gloperate
<commit_msg>Final fix for collision sampling<commit_after>
#include <gloperate/painter/CameraCollisionCapability.h>

#include <limits>

#include <glm/gtc/matrix_transform.hpp>

#include <glbinding/gl/enum.h>
#include <glbinding/gl/functions.h>
#include <glbinding/gl/bitfield.h>
#include <glbinding/gl/types.h>

#include <globjects/Framebuffer.h>

using namespace gl;

namespace gloperate
{

CameraCollisionCapability::CameraCollisionCapability()
: m_fbo(nullptr)
, m_size(1024)
, m_samplingSize(1)
{

}

CameraCollisionCapability::~CameraCollisionCapability()
{

}

void CameraCollisionCapability::setCollisionFBO(globjects::ref_ptr<globjects::Framebuffer> collisionFBO, size_t texSize)
{
    m_fbo = collisionFBO;
    m_size = texSize;
}

void CameraCollisionCapability::setSamplingSize(size_t samplingSize)
{
    m_samplingSize = samplingSize;
}

float CameraCollisionCapability::getDistance(const glm::vec3 &dir) const
{
    if(!m_fbo)
    {
        return std::numeric_limits<float>::max();
    }

    float xAbs = std::abs(dir.x);
    float yAbs = std::abs(dir.y);
    float zAbs = std::abs(dir.z);
    float main, u, v;
    GLenum face;

    if(xAbs == 0 && yAbs == 0 && zAbs == 0)
    {
        return std::numeric_limits<float>::max();
    }

    // Find the correct axis to sample
    if(xAbs > yAbs && xAbs > zAbs)
    {
        face = GL_COLOR_ATTACHMENT0;
        main = dir.x; u = -dir.z; v = -dir.y;
    } else if(yAbs > zAbs)
    {
        auto sign = std::signbit(dir.y) ? -1 : 1;

        face = GL_COLOR_ATTACHMENT2;
        main = dir.y; u = dir.x; v = sign *dir.z;

    } else
    {
        face = GL_COLOR_ATTACHMENT4;
        main = dir.z; u = -dir.x; v = -dir.y;
    }

    // Find the correct orientation on this axis
    face = face + static_cast<int>(std::signbit(main));

    // Sample the coordinates
    glm::vec2 uv{u/std::abs(main), v/std::abs(main)};
    glm::ivec2 i_uv = uv * static_cast<float>(m_size/2)+static_cast<float>(m_size/2);
    std::vector<glm::vec3> buf(m_samplingSize*m_samplingSize);

    m_fbo->bind();

    std::array<GLint,4> sampleRange{i_uv.x,i_uv.y,m_samplingSize,m_samplingSize};
    m_fbo->readPixels(face, sampleRange,GL_RGB,GL_FLOAT,buf.data());

    m_fbo->unbind();

    return buf[0].x;
}

} // namespace gloperate
<|endoftext|>


<commit_before>// [WriteFile Name=LoadWfsXmlQuery, Category=Layers]
// [Legal]
// Copyright 2019 Esri.

// 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.
// [Legal]

#include "LoadWfsXmlQuery.h"

#include "Map.h"
#include "MapQuickView.h"
#include "FeatureLayer.h"
#include "WfsFeatureTable.h"

using namespace Esri::ArcGISRuntime;

namespace
{
  static const QString xmlQueryString = R"(
                                        <wfs:GetFeature service="WFS" version="2.0.0"
                                        xmlns:Seattle_Downtown_Features="https://dservices2.arcgis.com/ZQgQTuoyBrtmoGdP/arcgis/services/Seattle_Downtown_Features/WFSServer"
                                        xmlns:wfs="http://www.opengis.net/wfs/2.0"
                                        xmlns:fes="http://www.opengis.net/fes/2.0"
                                        xmlns:gml="http://www.opengis.net/gml/3.2">
                                        <wfs:Query typeNames="Seattle_Downtown_Features:Trees">
                                        <fes:Filter>
                                        <fes:PropertyIsLike wildCard="*" escapeChar="\">
                                        <fes:ValueReference>Trees:SCIENTIFIC</fes:ValueReference>
                                        <fes:Literal>Tilia *</fes:Literal>
                                        </fes:PropertyIsLike>
                                        </fes:Filter>
                                        </wfs:Query>
                                        </wfs:GetFeature>
                                        )";
}

LoadWfsXmlQuery::LoadWfsXmlQuery(QObject* parent /* = nullptr */):
  QObject(parent),
  m_map(new Map(Basemap::navigationVector(this), this))
{
  // create WFS Feature Table
  const QUrl featureTableUrl("https://dservices2.arcgis.com/ZQgQTuoyBrtmoGdP/arcgis/services/Seattle_Downtown_Features/WFSServer?service=wfs&request=getcapabilities");
  WfsFeatureTable* wfsFeatureTable = new WfsFeatureTable(featureTableUrl,
                                                         "Seattle_Downtown_Features:Trees",
                                                         this);
  wfsFeatureTable->setFeatureRequestMode(FeatureRequestMode::ManualCache);

  // connect to feature table doneLoading signal
  connect(wfsFeatureTable, &WfsFeatureTable::doneLoading, this, [wfsFeatureTable, this](Error e)
  {
    if (!e.isEmpty())
      return;

    // populate the table with XML Query
    wfsFeatureTable->populateFromService(xmlQueryString, true);

    // set the viewpoint to the center of the extent
    m_mapView->setViewpointGeometry(wfsFeatureTable->extent(), 50);
  });

  // create Feature Layer
  FeatureLayer* featureLayer = new FeatureLayer(wfsFeatureTable, this);

  // add layer to the map
  m_map->operationalLayers()->append(featureLayer);
}

LoadWfsXmlQuery::~LoadWfsXmlQuery() = default;

void LoadWfsXmlQuery::init()
{
  // Register the map view for QML
  qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView");
  qmlRegisterType<LoadWfsXmlQuery>("Esri.Samples", 1, 0, "LoadWfsXmlQuerySample");
}

MapQuickView* LoadWfsXmlQuery::mapView() const
{
  return m_mapView;
}

// Set the view (created in QML)
void LoadWfsXmlQuery::setMapView(MapQuickView* mapView)
{
  if (!mapView || mapView == m_mapView)
    return;

  m_mapView = mapView;
  m_mapView->setMap(m_map);

  emit mapViewChanged();
}
<commit_msg>reformatting query<commit_after>// [WriteFile Name=LoadWfsXmlQuery, Category=Layers]
// [Legal]
// Copyright 2019 Esri.

// 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.
// [Legal]

#include "LoadWfsXmlQuery.h"

#include "Map.h"
#include "MapQuickView.h"
#include "FeatureLayer.h"
#include "WfsFeatureTable.h"

using namespace Esri::ArcGISRuntime;

namespace
{
  const QString xmlQueryString = R"(
    <wfs:GetFeature service="WFS" version="2.0.0"
      xmlns:Seattle_Downtown_Features="https://dservices2.arcgis.com/ZQgQTuoyBrtmoGdP/arcgis/services/Seattle_Downtown_Features/WFSServer"
      xmlns:wfs="http://www.opengis.net/wfs/2.0"
      xmlns:fes="http://www.opengis.net/fes/2.0"
      xmlns:gml="http://www.opengis.net/gml/3.2">
      <wfs:Query typeNames="Seattle_Downtown_Features:Trees">
        <fes:Filter>
        <fes:PropertyIsLike wildCard="*" escapeChar="\">
        <fes:ValueReference>Trees:SCIENTIFIC</fes:ValueReference>
        <fes:Literal>Tilia *</fes:Literal>
        </fes:PropertyIsLike>
        </fes:Filter>
      </wfs:Query>
    </wfs:GetFeature>)";
}

LoadWfsXmlQuery::LoadWfsXmlQuery(QObject* parent /* = nullptr */):
  QObject(parent),
  m_map(new Map(Basemap::navigationVector(this), this))
{
  // create WFS Feature Table
  const QUrl featureTableUrl("https://dservices2.arcgis.com/ZQgQTuoyBrtmoGdP/arcgis/services/Seattle_Downtown_Features/WFSServer?service=wfs&request=getcapabilities");
  WfsFeatureTable* wfsFeatureTable = new WfsFeatureTable(featureTableUrl,
                                                         "Seattle_Downtown_Features:Trees",
                                                         this);
  wfsFeatureTable->setFeatureRequestMode(FeatureRequestMode::ManualCache);

  // connect to feature table doneLoading signal
  connect(wfsFeatureTable, &WfsFeatureTable::doneLoading, this, [wfsFeatureTable, this](Error e)
  {
    if (!e.isEmpty())
      return;

    // populate the table with XML Query
    wfsFeatureTable->populateFromService(xmlQueryString, true);

    // set the viewpoint to the center of the extent
    m_mapView->setViewpointGeometry(wfsFeatureTable->extent(), 50);
  });

  // create Feature Layer
  FeatureLayer* featureLayer = new FeatureLayer(wfsFeatureTable, this);

  // add layer to the map
  m_map->operationalLayers()->append(featureLayer);
}

LoadWfsXmlQuery::~LoadWfsXmlQuery() = default;

void LoadWfsXmlQuery::init()
{
  // Register the map view for QML
  qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView");
  qmlRegisterType<LoadWfsXmlQuery>("Esri.Samples", 1, 0, "LoadWfsXmlQuerySample");
}

MapQuickView* LoadWfsXmlQuery::mapView() const
{
  return m_mapView;
}

// Set the view (created in QML)
void LoadWfsXmlQuery::setMapView(MapQuickView* mapView)
{
  if (!mapView || mapView == m_mapView)
    return;

  m_mapView = mapView;
  m_mapView->setMap(m_map);

  emit mapViewChanged();
}
<|endoftext|>


<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <iostream>
#include "cppa/to_string.hpp"

#include "cppa/self.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/abstract_event_based_actor.hpp"

namespace cppa {

abstract_event_based_actor::abstract_event_based_actor()
    : super(super::blocked)
{
    //m_mailbox_pos = m_mailbox.cache().end();
}

void abstract_event_based_actor::dequeue(behavior&)
{
    quit(exit_reason::unallowed_function_call);
}

void abstract_event_based_actor::dequeue(partial_function&)
{
    quit(exit_reason::unallowed_function_call);
}

auto abstract_event_based_actor::handle_message(mailbox_element& node) -> handle_message_result
{
    CPPA_REQUIRE(m_loop_stack.empty() == false);
    auto& bhvr = *(m_loop_stack.back());
    switch (filter_msg(node.msg))
    {
        case normal_exit_signal:
        case expired_timeout_message:
            return drop_msg;

        case timeout_message:
            m_has_pending_timeout_request = false;
            CPPA_REQUIRE(bhvr.timeout().valid());
            bhvr.handle_timeout();
            if (!m_loop_stack.empty())
            {
                auto& next_bhvr = *(m_loop_stack.back());
                request_timeout(next_bhvr.timeout());
            }
            return msg_handled;

        default:
            break;
    }
    std::swap(m_last_dequeued, node.msg);
    std::swap(m_last_sender, node.sender);
    //m_last_dequeued = node.msg;
    //m_last_sender = node.sender;
    // make sure no timeout is handled incorrectly in a nested receive
    ++m_active_timeout_id;
    if ((bhvr.get_partial_function())(m_last_dequeued))
    {
        m_last_dequeued.reset();
        m_last_sender.reset();
        // we definitely don't have a pending timeout now
        m_has_pending_timeout_request = false;
        return msg_handled;
    }
    // no match, restore members
    --m_active_timeout_id;
    std::swap(m_last_dequeued, node.msg);
    std::swap(m_last_sender, node.sender);
    return cache_msg;
}

void abstract_event_based_actor::resume(util::fiber*, scheduler::callback* cb)
{
    auto done_cb = [&]()
    {
        m_state.store(abstract_scheduled_actor::done);
        m_loop_stack.clear();
        on_exit();
        cb->exec_done();
    };
    self.set(this);
    try
    {
        std::unique_ptr<detail::recursive_queue_node> e;
        for (;;)
        {
            e.reset(m_mailbox.try_pop());
            if (!e)
            {
                m_state.store(abstract_scheduled_actor::about_to_block);
                CPPA_MEMORY_BARRIER();
                if (m_mailbox.can_fetch_more() == false)
                {
                    switch (compare_exchange_state(abstract_scheduled_actor::about_to_block,
                                                   abstract_scheduled_actor::blocked))
                    {
                        case abstract_scheduled_actor::ready:
                        {
                            break;
                        }
                        case abstract_scheduled_actor::blocked:
                        {
                            return;
                        }
                        default: exit(7); // illegal state
                    };
                }
            }
            else
            {
                switch (handle_message(*e))
                {
                    case drop_msg:
                    {
                        break; // nop
                    }
                    case msg_handled:
                    {
                        if (m_loop_stack.empty())
                        {
                            done_cb();
                            return;
                        }
                        // try to match cached messages before receiving new ones
                        auto i = m_cache.begin();
                        while (i != m_cache.end())
                        {
                            switch (handle_message(*(*i)))
                            {
                                case drop_msg:
                                {
                                    i = m_cache.erase(i);
                                    break;
                                }
                                case msg_handled:
                                {
                                    m_cache.erase(i);
                                    if (m_loop_stack.empty())
                                    {
                                        done_cb();
                                        return;
                                    }
                                    i = m_cache.begin();
                                    break;
                                }
                                case cache_msg:
                                {
                                    ++i;
                                    break;
                                }
                                default: exit(7); // illegal state
                            }
                        }
                        break;
                    }
                    case cache_msg:
                    {
                        m_cache.push_back(std::move(e));
                        break;
                    }
                    default: exit(7); // illegal state
                }
            }
        }
    }
    catch (actor_exited& what)
    {
        cleanup(what.reason());
    }
    catch (...)
    {
        cleanup(exit_reason::unhandled_exception);
    }
    done_cb();
}

void abstract_event_based_actor::on_exit()
{
}

} // namespace cppa
<commit_msg>removed obsolete code<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <iostream>
#include "cppa/to_string.hpp"

#include "cppa/self.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/abstract_event_based_actor.hpp"

namespace cppa {

abstract_event_based_actor::abstract_event_based_actor()
    : super(super::blocked)
{
    //m_mailbox_pos = m_mailbox.cache().end();
}

void abstract_event_based_actor::dequeue(behavior&)
{
    quit(exit_reason::unallowed_function_call);
}

void abstract_event_based_actor::dequeue(partial_function&)
{
    quit(exit_reason::unallowed_function_call);
}

auto abstract_event_based_actor::handle_message(mailbox_element& node) -> handle_message_result
{
    CPPA_REQUIRE(m_loop_stack.empty() == false);
    auto& bhvr = *(m_loop_stack.back());
    switch (filter_msg(node.msg))
    {
        case normal_exit_signal:
        case expired_timeout_message:
            return drop_msg;

        case timeout_message:
            m_has_pending_timeout_request = false;
            CPPA_REQUIRE(bhvr.timeout().valid());
            bhvr.handle_timeout();
            if (!m_loop_stack.empty())
            {
                auto& next_bhvr = *(m_loop_stack.back());
                request_timeout(next_bhvr.timeout());
            }
            return msg_handled;

        default:
            break;
    }
    std::swap(m_last_dequeued, node.msg);
    std::swap(m_last_sender, node.sender);
    //m_last_dequeued = node.msg;
    //m_last_sender = node.sender;
    if ((bhvr.get_partial_function())(m_last_dequeued))
    {
        m_last_dequeued.reset();
        m_last_sender.reset();
        // we definitely don't have a pending timeout now
        m_has_pending_timeout_request = false;
        return msg_handled;
    }
    // no match, restore members
    std::swap(m_last_dequeued, node.msg);
    std::swap(m_last_sender, node.sender);
    return cache_msg;
}

void abstract_event_based_actor::resume(util::fiber*, scheduler::callback* cb)
{
    auto done_cb = [&]()
    {
        m_state.store(abstract_scheduled_actor::done);
        m_loop_stack.clear();
        on_exit();
        cb->exec_done();
    };
    self.set(this);
    try
    {
        std::unique_ptr<detail::recursive_queue_node> e;
        for (;;)
        {
            e.reset(m_mailbox.try_pop());
            if (!e)
            {
                m_state.store(abstract_scheduled_actor::about_to_block);
                CPPA_MEMORY_BARRIER();
                if (m_mailbox.can_fetch_more() == false)
                {
                    switch (compare_exchange_state(abstract_scheduled_actor::about_to_block,
                                                   abstract_scheduled_actor::blocked))
                    {
                        case abstract_scheduled_actor::ready:
                        {
                            break;
                        }
                        case abstract_scheduled_actor::blocked:
                        {
                            return;
                        }
                        default: exit(7); // illegal state
                    };
                }
            }
            else
            {
                switch (handle_message(*e))
                {
                    case drop_msg:
                    {
                        break; // nop
                    }
                    case msg_handled:
                    {
                        if (m_loop_stack.empty())
                        {
                            done_cb();
                            return;
                        }
                        // try to match cached messages before receiving new ones
                        auto i = m_cache.begin();
                        while (i != m_cache.end())
                        {
                            switch (handle_message(*(*i)))
                            {
                                case drop_msg:
                                {
                                    i = m_cache.erase(i);
                                    break;
                                }
                                case msg_handled:
                                {
                                    m_cache.erase(i);
                                    if (m_loop_stack.empty())
                                    {
                                        done_cb();
                                        return;
                                    }
                                    i = m_cache.begin();
                                    break;
                                }
                                case cache_msg:
                                {
                                    ++i;
                                    break;
                                }
                                default: exit(7); // illegal state
                            }
                        }
                        break;
                    }
                    case cache_msg:
                    {
                        m_cache.push_back(std::move(e));
                        break;
                    }
                    default: exit(7); // illegal state
                }
            }
        }
    }
    catch (actor_exited& what)
    {
        cleanup(what.reason());
    }
    catch (...)
    {
        cleanup(exit_reason::unhandled_exception);
    }
    done_cb();
}

void abstract_event_based_actor::on_exit()
{
}

} // namespace cppa
<|endoftext|>


<commit_before>#include "OI.h"
#include "Commands/ControlIntakeWheels.h"
#include "Subsystems/IntakeWheel.h"
#include "Misc/ToggleClass.h"

/// Default constructor of the class.
ControlIntakeWheels::ControlIntakeWheels()
{
	IntakeArmPosition = new Toggle<bool>(false,true);
	Requires(IntakeWheel::GetInstance());
}

/// Called just before this Command runs the first time.
void ControlIntakeWheels::Initialize()
{
	IntakeWheel::GetInstance()->SpinIntake(0);
}

void ControlIntakeWheels::Execute()
{
	OI* oi = OI::GetInstance();

	//In and out control for the intake bar
	if(oi->gamepad->GetRawButton(BTN_INTAKE))
	{
		IntakeWheel::GetInstance()->SpinIntake(Preferences::GetInstance()->GetDouble("Intake Speed",1));
	}else if(oi->gamepad->GetRawButton(BTN_OUTAKE)){
		IntakeWheel::GetInstance()->SpinIntake(-Preferences::GetInstance()->GetDouble("Intake Speed",1));
	}else{
		IntakeWheel::GetInstance()->SpinIntake(0);
	}
}

/// Make this return true when this Command no longer needs to run execute().
/// \return always false since this is the default command and should never finish.
bool ControlIntakeWheels::IsFinished()
{
	return false;
}

/// Called once after isFinished returns true
void ControlIntakeWheels::End()
{
	IntakeWheel::GetInstance()->SpinIntake(0);
}

/// Called when another command which requires one or more of the same
/// subsystems is scheduled to run
void ControlIntakeWheels::Interrupted()
{
	End();
}
<commit_msg>Added a second throttle specifically for intake wheels out.<commit_after>#include "OI.h"
#include "Commands/ControlIntakeWheels.h"
#include "Subsystems/IntakeWheel.h"
#include "Misc/ToggleClass.h"

/// Default constructor of the class.
ControlIntakeWheels::ControlIntakeWheels()
{
	IntakeArmPosition = new Toggle<bool>(false,true);
	Requires(IntakeWheel::GetInstance());
}

/// Called just before this Command runs the first time.
void ControlIntakeWheels::Initialize()
{
	IntakeWheel::GetInstance()->SpinIntake(0);
}

void ControlIntakeWheels::Execute()
{
	OI* oi = OI::GetInstance();

	//In and out control for the intake bar
	if(oi->gamepad->GetRawButton(BTN_INTAKE))
	{
		IntakeWheel::GetInstance()->SpinIntake(Preferences::GetInstance()->GetDouble("Intake Speed",1));
	}else if(oi->gamepad->GetRawButton(BTN_OUTAKE)){
		IntakeWheel::GetInstance()->SpinIntake(Preferences::GetInstance()->GetDouble("Intake Speed Out",-1));
	}else{
		IntakeWheel::GetInstance()->SpinIntake(0);
	}
}

/// Make this return true when this Command no longer needs to run execute().
/// \return always false since this is the default command and should never finish.
bool ControlIntakeWheels::IsFinished()
{
	return false;
}

/// Called once after isFinished returns true
void ControlIntakeWheels::End()
{
	IntakeWheel::GetInstance()->SpinIntake(0);
}

/// Called when another command which requires one or more of the same
/// subsystems is scheduled to run
void ControlIntakeWheels::Interrupted()
{
	End();
}
<|endoftext|>


<commit_before>

#ifndef ONI_VICON_RECORDER_ONI_RECORDER_HPP
#define ONI_VICON_RECORDER_ONI_RECORDER_HPP

#include <string>
#include <map>

#include <boost/thread/mutex.hpp>

#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>

#include <oni_vicon_recorder/RunDepthSensorAction.h>
#include <oni_vicon_recorder/ChangeDepthSensorModeAction.h>

#include "kinect.h"

#define KINECT_IMAGE_COLS       640
#define KINECT_IMAGE_ROWS       480

#define KINECT_RGB_FOCAL_LENGTH_DEFAULT     525
#define KINECT_RGB_CENTER_COL_DEFAULT       320
#define KINECT_RGB_CENTER_ROW_DEFAULT       240
#define KINECT_IR_FOCAL_LENGTH_DEFAULT      580
#define KINECT_IR_CENTER_COL_DEFAULT        320
#define KINECT_IR_CENTER_ROW_DEFAULT        240
#define KINECT_RGB_TO_IR_X_DEFAULT          (-0.0254)
#define KINECT_RGB_TO_IR_Y_DEFAULT          (-0.00013)
#define KINECT_RGB_TO_IR_Z_DEFAULT          (-0.00218)
#define KINECT_RGB_TO_IR_ROLL_DEFAULT       0.0 // rad
#define KINECT_RGB_TO_IR_PITCH_DEFAULT      0.0 // rad
#define KINECT_RGB_TO_IR_YAW_DEFAULT        0.0 // rad

#define KINECT_VENDOR_ID                    0x45e
#define XTION_VENDOR_ID                     0x1d27

#define CHECK_RC(rc, what)									    \
if (rc != XN_STATUS_OK)											\
{																\
    ROS_ERROR("%s failed: %s\n", what, xnGetStatusString(rc));  \
    return false;												\
}

class OniRecorder
{
public:

public:
    OniRecorder(ros::NodeHandle& node_handle);
    ~OniRecorder();

    void changeDeptSensorModeCB(const oni_vicon_recorder::ChangeDepthSensorModeGoalConstPtr &goal);
    void runDepthSensorCB(const oni_vicon_recorder::RunDepthSensorGoalConstPtr& goal);
    bool closeDevice();

    bool startRecording(std::string file);
    bool stopRecording();
    int countFrames();
    bool isRecording();

    std::map<std::string, XnMapOutputMode> getSupportedModes(const DepthGenerator *generator);
    std::vector<std::string> getSupportedModeList(const std::map<std::string, XnMapOutputMode>& mode_map);
    XnMapOutputMode getCurrentMode(const DepthGenerator *generator) const;
    std::string getModeName(const XnMapOutputMode& mode) const;

private:
    ros::NodeHandle node_handle_;
    kinect_t* kinect_;
    Recorder recorder_;
    bool recording_;
    bool running_;
    int frames;
    boost::shared_mutex frameLock_;
    std::map<std::string, XnMapOutputMode> modes_;

    actionlib::SimpleActionServer<
        oni_vicon_recorder::RunDepthSensorAction> run_depth_sensor_as_;
    actionlib::SimpleActionServer<
        oni_vicon_recorder::ChangeDepthSensorModeAction> change_depth_sensor_mode_as_;
};

#endif
<commit_msg>Added former rosbuild arm_rgbd package as rgbd_sensor catkin package<commit_after>

#ifndef ONI_VICON_RECORDER_ONI_RECORDER_HPP
#define ONI_VICON_RECORDER_ONI_RECORDER_HPP

#include <string>
#include <map>
#include <signal.h>

#include <boost/thread/mutex.hpp>
#include <boost/format.hpp>

// ROS
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <sensor_msgs/CameraInfo.h>
#include <stereo_msgs/DisparityImage.h>
#include <sensor_msgs/image_encodings.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <tf/transform_listener.h>
#include <actionlib/server/simple_action_server.h>

#include <oni_vicon_recorder/RunDepthSensorAction.h>
#include <oni_vicon_recorder/ChangeDepthSensorModeAction.h>

#include "kinect.h"

#define KINECT_IMAGE_COLS       640
#define KINECT_IMAGE_ROWS       480

#define KINECT_RGB_FOCAL_LENGTH_DEFAULT     525
#define KINECT_RGB_CENTER_COL_DEFAULT       320
#define KINECT_RGB_CENTER_ROW_DEFAULT       240
#define KINECT_IR_FOCAL_LENGTH_DEFAULT      580
#define KINECT_IR_CENTER_COL_DEFAULT        320
#define KINECT_IR_CENTER_ROW_DEFAULT        240
#define KINECT_RGB_TO_IR_X_DEFAULT          (-0.0254)
#define KINECT_RGB_TO_IR_Y_DEFAULT          (-0.00013)
#define KINECT_RGB_TO_IR_Z_DEFAULT          (-0.00218)
#define KINECT_RGB_TO_IR_ROLL_DEFAULT       0.0 // rad
#define KINECT_RGB_TO_IR_PITCH_DEFAULT      0.0 // rad
#define KINECT_RGB_TO_IR_YAW_DEFAULT        0.0 // rad

#define KINECT_VENDOR_ID                    0x45e
#define XTION_VENDOR_ID                     0x1d27

#define CHECK_RC(rc, what)									    \
if (rc != XN_STATUS_OK)											\
{																\
    ROS_ERROR("%s failed: %s\n", what, xnGetStatusString(rc));  \
    return false;												\
}

class OniRecorder
{
public:

public:
    OniRecorder(ros::NodeHandle& node_handle);
    ~OniRecorder();

    void changeDeptSensorModeCB(const oni_vicon_recorder::ChangeDepthSensorModeGoalConstPtr &goal);
    void runDepthSensorCB(const oni_vicon_recorder::RunDepthSensorGoalConstPtr& goal);
    bool closeDevice();

    bool startRecording(std::string file);
    bool stopRecording();
    int countFrames();
    bool isRecording();

    std::map<std::string, XnMapOutputMode> getSupportedModes(const DepthGenerator *generator);
    std::vector<std::string> getSupportedModeList(const std::map<std::string, XnMapOutputMode>& mode_map);
    XnMapOutputMode getCurrentMode(const DepthGenerator *generator) const;
    std::string getModeName(const XnMapOutputMode& mode) const;

private:
    ros::NodeHandle node_handle_;
    kinect_t* kinect_;
    Recorder recorder_;
    bool recording_;
    bool running_;
    int frames;
    boost::shared_mutex frameLock_;
    std::map<std::string, XnMapOutputMode> modes_;

    actionlib::SimpleActionServer<
        oni_vicon_recorder::RunDepthSensorAction> run_depth_sensor_as_;
    actionlib::SimpleActionServer<
        oni_vicon_recorder::ChangeDepthSensorModeAction> change_depth_sensor_mode_as_;

    image_transport::ImageTransport* it_;
    std::string camera_name_;
    std::string frame_id_;
    sensor_msgs::Image gray_image_;
    sensor_msgs::CameraInfo depth_cam_info_;

    std::string calib_url_;

    // Standard parameters
    bool bus_reset_;
    std::string bayer_pattern_;
    std::string encoding_;
    std::string guid_;
    int iso_speed_;
    std::string video_mode_;

    inline bool isDepthStreamRequired() const;

    sensor_msgs::CameraInfoPtr fillCameraInfo (ros::Time time, bool is_rgb);
    void subscriberChangedEvent ();

    bool calibration_valid_;
    bool calibration_loaded_;

    // Publishers Camera Info
    ros::Publisher pub_depth_info_;
    // Publishers Images
    image_transport::Publisher pub_gray_image_;
    image_transport::Publisher pub_depth_image_;
    // Publishers Point Clouds
    ros::Publisher pub_disp_image_;
    ros::Publisher pub_point_cloud_;
    ros::Publisher pub_point_cloud_rgb_;

    // publish methods
    void publishGrayImage (ros::Time time);
    void publishDepthImage (ros::Time time);
    void publishDisparity (ros::Time time);
    void publishXYZPointCloud (ros::Time time);

    std::string depth_frame_id_;
    unsigned image_width_;
    unsigned image_height_;
    unsigned depth_width_;
    unsigned depth_height_;
};

#endif
<|endoftext|>