<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
//
// A brpc based redis-server. Currently just implement set and
// get, but it's sufficient that you can get the idea how to
// implement brpc::RedisCommandHandler.

#include <brpc/server.h>
#include <brpc/redis.h>
#include <butil/crc32c.h>
#include <butil/strings/string_split.h>
#include <gflags/gflags.h>
#include <unordered_map>

class RedisServiceImpl : public brpc::RedisService {
public:
    bool Set(const std::string& key, const std::string& value) {
        int slot = butil::crc32c::Value(key.c_str(), key.size()) % kHashSlotNum;
        _mutex[slot].lock();
        _map[slot][key] = value;
        _mutex[slot].unlock();
        return true;
    }

    bool Get(const std::string& key, std::string* value) {
        int slot = butil::crc32c::Value(key.c_str(), key.size()) % kHashSlotNum;
        _mutex[slot].lock();
        auto it = _map[slot].find(key);
        if (it == _map[slot].end()) {
            _mutex[slot].unlock();
            return false;
        }
        *value = it->second;
        _mutex[slot].unlock();
        return true;
    }

private:
    const static int kHashSlotNum = 32;
    std::unordered_map<std::string, std::string> _map[kHashSlotNum];
    butil::Mutex _mutex[kHashSlotNum];
};

class GetCommandHandler : public brpc::RedisCommandHandler {
public:
    GetCommandHandler(RedisServiceImpl* rsimpl)
        : _rsimpl(rsimpl) {}

    brpc::RedisCommandHandler::Result Run(int size, const char* args[],
                                          brpc::RedisReply* output,
                                          bool is_last) override {
        if (size <= 1) {
            output->SetError("ERR wrong number of arguments for 'get' command");
            return brpc::RedisCommandHandler::OK;
        }
        const std::string key(args[1]);
        std::string value;
        if (_rsimpl->Get(key, &value)) {
            output->SetString(value);
        } else {
            output->SetNullString();
        }
        return brpc::RedisCommandHandler::OK;
	}

private:
   	RedisServiceImpl* _rsimpl;
};

class SetCommandHandler : public brpc::RedisCommandHandler {
public:
    SetCommandHandler(RedisServiceImpl* rsimpl)
        : _rsimpl(rsimpl) {}

    brpc::RedisCommandHandler::Result Run(int size, const char* args[],
                                          brpc::RedisReply* output,
                                          bool is_last) override {
        if (size <= 2) {
            output->SetError("ERR wrong number of arguments for 'set' command");
            return brpc::RedisCommandHandler::OK;
        }
        const std::string key(args[1]);
        const std::string value(args[2]);
        _rsimpl->Set(key, value);
        output->SetStatus("OK");
        return brpc::RedisCommandHandler::OK;
	}

private:
   	RedisServiceImpl* _rsimpl;
};

int main(int argc, char* argv[]) {
    google::ParseCommandLineFlags(&argc, &argv, true);
    RedisServiceImpl* rsimpl = new RedisServiceImpl;
    rsimpl->AddCommandHandler("get", new GetCommandHandler(rsimpl));
    rsimpl->AddCommandHandler("set", new SetCommandHandler(rsimpl));

    brpc::Server server;
    brpc::ServerOptions server_options;
    server_options.redis_service = rsimpl;
    if (server.Start(6379, &server_options) != 0) {
        LOG(ERROR) << "Fail to start server";
        return -1;
    }
    server.RunUntilAskedToQuit();
    return 0;
}
<commit_msg>redis_server_protocol: update redis-server<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
//
// A brpc based redis-server. Currently just implement set and
// get, but it's sufficient that you can get the idea how to
// implement brpc::RedisCommandHandler.

#include <brpc/server.h>
#include <brpc/redis.h>
#include <butil/crc32c.h>
#include <butil/strings/string_split.h>
#include <gflags/gflags.h>
#include <unordered_map>

class RedisServiceImpl : public brpc::RedisService {
public:
    bool Set(const std::string& key, const std::string& value) {
        int slot = butil::crc32c::Value(key.c_str(), key.size()) % kHashSlotNum;
        _mutex[slot].lock();
        _map[slot][key] = value;
        _mutex[slot].unlock();
        return true;
    }

    bool Get(const std::string& key, std::string* value) {
        int slot = butil::crc32c::Value(key.c_str(), key.size()) % kHashSlotNum;
        _mutex[slot].lock();
        auto it = _map[slot].find(key);
        if (it == _map[slot].end()) {
            _mutex[slot].unlock();
            return false;
        }
        *value = it->second;
        _mutex[slot].unlock();
        return true;
    }

private:
    const static int kHashSlotNum = 32;
    std::unordered_map<std::string, std::string> _map[kHashSlotNum];
    butil::Mutex _mutex[kHashSlotNum];
};

class GetCommandHandler : public brpc::RedisCommandHandler {
public:
    GetCommandHandler(RedisServiceImpl* rsimpl)
        : _rsimpl(rsimpl) {}

    brpc::RedisCommandHandler::Result Run(const std::vector<const char*>& args,
                                          brpc::RedisReply* output,
                                          bool is_last) override {
        if (args.size() <= 1) {
            output->SetError("ERR wrong number of arguments for 'get' command");
            return brpc::RedisCommandHandler::OK;
        }
        const std::string key(args[1]);
        std::string value;
        if (_rsimpl->Get(key, &value)) {
            output->SetString(value);
        } else {
            output->SetNullString();
        }
        return brpc::RedisCommandHandler::OK;
	}

private:
   	RedisServiceImpl* _rsimpl;
};

class SetCommandHandler : public brpc::RedisCommandHandler {
public:
    SetCommandHandler(RedisServiceImpl* rsimpl)
        : _rsimpl(rsimpl) {}

    brpc::RedisCommandHandler::Result Run(const std::vector<const char*>& args,
                                          brpc::RedisReply* output,
                                          bool is_last) override {
        if (args.size() <= 2) {
            output->SetError("ERR wrong number of arguments for 'set' command");
            return brpc::RedisCommandHandler::OK;
        }
        const std::string key(args[1]);
        const std::string value(args[2]);
        _rsimpl->Set(key, value);
        output->SetStatus("OK");
        return brpc::RedisCommandHandler::OK;
	}

private:
   	RedisServiceImpl* _rsimpl;
};

int main(int argc, char* argv[]) {
    google::ParseCommandLineFlags(&argc, &argv, true);
    RedisServiceImpl* rsimpl = new RedisServiceImpl;
    rsimpl->AddCommandHandler("get", new GetCommandHandler(rsimpl));
    rsimpl->AddCommandHandler("set", new SetCommandHandler(rsimpl));

    brpc::Server server;
    brpc::ServerOptions server_options;
    server_options.redis_service = rsimpl;
    if (server.Start(6379, &server_options) != 0) {
        LOG(ERROR) << "Fail to start server";
        return -1;
    }
    server.RunUntilAskedToQuit();
    return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "GlobalContext.hpp"
#include "Variable.hpp"
#include "Utils.hpp"
#include "VisitorUtils.hpp"
#include "Type.hpp"
#include "mangling.hpp"

#include "ast/GetConstantValue.hpp"

using namespace eddic;

GlobalContext::GlobalContext(Platform platform) : Context(NULL), platform(platform) {
    Val zero = 0;

    variables["_mem_start"] = std::make_shared<Variable>("_mem_start", INT, Position(PositionType::GLOBAL, "_mem_start"), zero);
    variables["_mem_last"] = std::make_shared<Variable>("_mem_last", INT, Position(PositionType::GLOBAL, "_mem_last"), zero);

    //In order to not display a warning
    variables["_mem_start"]->add_reference();
    variables["_mem_last"]->add_reference();

    defineStandardFunctions();
}

std::unordered_map<std::string, std::shared_ptr<Variable>> GlobalContext::getVariables(){
    return variables;
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, std::shared_ptr<const Type> type){
    //Only global array have no value, other types have all values
    assert(type->is_array());

    Position position(PositionType::GLOBAL, variable);

    return variables[variable] = std::make_shared<Variable>(variable, type, position);
}

std::shared_ptr<Variable> GlobalContext::generate_variable(const std::string&, std::shared_ptr<const Type>){
    eddic_unreachable("Cannot generate global variable");
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, std::shared_ptr<const Type> type, ast::Value& value){
    auto val = visit(ast::GetConstantValue(), value);

    if(type->is_const()){
        Position position(PositionType::CONST);
        return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
    }

    Position position(PositionType::GLOBAL, variable);
    return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
}

Function& GlobalContext::add_function(std::shared_ptr<const Type> ret, const std::string& name, const std::string& mangled_name){
    m_functions.emplace(std::piecewise_construct, std::forward_as_tuple(mangled_name), std::forward_as_tuple(ret, name, mangled_name));

    return m_functions.at(mangled_name);
}

Function& GlobalContext::getFunction(const std::string& function){
    eddic_assert(exists(function), "The function must exists");

    return m_functions.at(function);
}

bool GlobalContext::exists(const std::string& function) const {
    return m_functions.find(function) != m_functions.end();
}

void GlobalContext::add_struct(std::shared_ptr<Struct> struct_){
    m_structs[struct_->name] = struct_;
}

bool GlobalContext::struct_exists(const std::string& struct_) const {
    return m_structs.find(struct_) != m_structs.end();
}

bool GlobalContext::struct_exists(std::shared_ptr<const Type> type) const {
    if(type->is_pointer()){
        type = type->data_type();
    }

    eddic_assert(type->is_custom_type() || type->is_template_type(), "This type has no corresponding struct");

    auto struct_name = type->mangle();
    return struct_exists(struct_name);
}

std::shared_ptr<Struct> GlobalContext::get_struct(const std::string& struct_name) const {
    auto it = m_structs.find(struct_name);

    if(it == m_structs.end()){
        return nullptr;
    } else {
        return it->second;
    }
}

std::shared_ptr<Struct> GlobalContext::get_struct(std::shared_ptr<const Type> type) const {
    if(!type){
        return nullptr;
    }

    if(type->is_pointer()){
        type = type->data_type();
    }

    eddic_assert(type->is_custom_type() || type->is_template_type(), "This type has no corresponding struct");

    auto struct_name = type->mangle();
    return get_struct(struct_name);
}

int GlobalContext::member_offset(std::shared_ptr<const Struct> struct_, const std::string& member) const {
    int offset = 0;

    for(auto& m : struct_->members){
        if(m->name == member){
            return offset;
        }

        offset += m->type->size(platform);
    }

    eddic_unreachable("The member is not part of the struct");
}

std::shared_ptr<const Type> GlobalContext::member_type(std::shared_ptr<const Struct> struct_, int offset) const {
    int current_offset = 0;
    std::shared_ptr<Member> member = nullptr;

    for(auto& m : struct_->members){
        member = m;

        if(offset <= current_offset){
            return member->type;
        }

        current_offset += m->type->size(platform);
    }

    return member->type;
}

int GlobalContext::self_size_of_struct(std::shared_ptr<const Struct> struct_) const {
    int struct_size = 0;

    for(auto& m : struct_->members){
        struct_size += m->type->size(platform);
    }

    return struct_size;
}

int GlobalContext::total_size_of_struct(std::shared_ptr<const Struct> struct_) const {
   int total = self_size_of_struct(struct_);

   while(struct_->parent_type){
       struct_ = get_struct(struct_->parent_type);
       total += self_size_of_struct(struct_);
   }

   return total;
}

bool GlobalContext::is_recursively_nested(std::shared_ptr<const Struct> struct_, unsigned int left) const {
    if(left == 0){
        return true;
    }

    for(auto& m : struct_->members){
        auto type = m->type;

        if(type->is_structure()){
            if(is_recursively_nested(get_struct(type), left - 1)){
                return true;
            }
        }
    }

    return false;
}

bool GlobalContext::is_recursively_nested(std::shared_ptr<const Struct> struct_) const {
    return is_recursively_nested(struct_, 100);
}

void GlobalContext::addReference(const std::string& function){
    ++(getFunction(function).references());
}

void GlobalContext::removeReference(const std::string& function){
    --(getFunction(function).references());
}

int GlobalContext::referenceCount(const std::string& function){
    return getFunction(function).references();
}

void GlobalContext::addPrintFunction(const std::string& function, std::shared_ptr<const Type> parameterType){
    auto& printFunction = add_function(VOID, "print", function);
    printFunction.standard() = true;
    printFunction.parameters().emplace_back("a", parameterType);
}

void GlobalContext::defineStandardFunctions(){
    auto& printLineFunction = add_function(VOID, "print", "_F7println");
    printLineFunction.standard() = true;

    //print string
    addPrintFunction("_F5printS", STRING);
    addPrintFunction("_F7printlnS", STRING);

    //print integer
    addPrintFunction("_F5printI", INT);
    addPrintFunction("_F7printlnI", INT);

    //print char
    addPrintFunction("_F5printC", CHAR);
    addPrintFunction("_F7printlnC", CHAR);

    //print float
    addPrintFunction("_F5printF", FLOAT);
    addPrintFunction("_F7printlnF", FLOAT);

    auto& read_char_function = add_function(CHAR, "read_char", "_F9read_char");
    read_char_function.standard() = true;

    //alloc function
    auto& allocFunction = add_function(new_pointer_type(INT), "alloc", "_F5allocI");
    allocFunction.standard() = true;
    allocFunction.parameters().emplace_back("a", INT);

    //free function
    auto& freeFunction = add_function(VOID, "free", "_F4freePI");
    freeFunction.standard() = true;
    freeFunction.parameters().emplace_back("a", INT);

    //time function
    auto& timeFunction = add_function(VOID, "time", "_F4timeAI");
    timeFunction.standard() = true;
    timeFunction.parameters().emplace_back("a", new_array_type(INT));

    //duration function
    auto& durationFunction = add_function(VOID, "duration", "_F8durationAIAI");
    durationFunction.standard() = true;
    durationFunction.parameters().emplace_back("a", new_array_type(INT));
    durationFunction.parameters().emplace_back("b", new_array_type(INT));
}

const GlobalContext::FunctionMap& GlobalContext::functions() const {
    return m_functions;
}

Platform GlobalContext::target_platform() const {
    return platform;
}

statistics& GlobalContext::stats(){
    return m_statistics;
}
<commit_msg>Use nullptr rather than NULL<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "GlobalContext.hpp"
#include "Variable.hpp"
#include "Utils.hpp"
#include "VisitorUtils.hpp"
#include "Type.hpp"
#include "mangling.hpp"

#include "ast/GetConstantValue.hpp"

using namespace eddic;

GlobalContext::GlobalContext(Platform platform) : Context(nullptr), platform(platform) {
    Val zero = 0;

    variables["_mem_start"] = std::make_shared<Variable>("_mem_start", INT, Position(PositionType::GLOBAL, "_mem_start"), zero);
    variables["_mem_last"] = std::make_shared<Variable>("_mem_last", INT, Position(PositionType::GLOBAL, "_mem_last"), zero);

    //In order to not display a warning
    variables["_mem_start"]->add_reference();
    variables["_mem_last"]->add_reference();

    defineStandardFunctions();
}

std::unordered_map<std::string, std::shared_ptr<Variable>> GlobalContext::getVariables(){
    return variables;
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, std::shared_ptr<const Type> type){
    //Only global array have no value, other types have all values
    assert(type->is_array());

    Position position(PositionType::GLOBAL, variable);

    return variables[variable] = std::make_shared<Variable>(variable, type, position);
}

std::shared_ptr<Variable> GlobalContext::generate_variable(const std::string&, std::shared_ptr<const Type>){
    eddic_unreachable("Cannot generate global variable");
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, std::shared_ptr<const Type> type, ast::Value& value){
    auto val = visit(ast::GetConstantValue(), value);

    if(type->is_const()){
        Position position(PositionType::CONST);
        return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
    }

    Position position(PositionType::GLOBAL, variable);
    return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
}

Function& GlobalContext::add_function(std::shared_ptr<const Type> ret, const std::string& name, const std::string& mangled_name){
    m_functions.emplace(std::piecewise_construct, std::forward_as_tuple(mangled_name), std::forward_as_tuple(ret, name, mangled_name));

    return m_functions.at(mangled_name);
}

Function& GlobalContext::getFunction(const std::string& function){
    eddic_assert(exists(function), "The function must exists");

    return m_functions.at(function);
}

bool GlobalContext::exists(const std::string& function) const {
    return m_functions.find(function) != m_functions.end();
}

void GlobalContext::add_struct(std::shared_ptr<Struct> struct_){
    m_structs[struct_->name] = struct_;
}

bool GlobalContext::struct_exists(const std::string& struct_) const {
    return m_structs.find(struct_) != m_structs.end();
}

bool GlobalContext::struct_exists(std::shared_ptr<const Type> type) const {
    if(type->is_pointer()){
        type = type->data_type();
    }

    eddic_assert(type->is_custom_type() || type->is_template_type(), "This type has no corresponding struct");

    auto struct_name = type->mangle();
    return struct_exists(struct_name);
}

std::shared_ptr<Struct> GlobalContext::get_struct(const std::string& struct_name) const {
    auto it = m_structs.find(struct_name);

    if(it == m_structs.end()){
        return nullptr;
    } else {
        return it->second;
    }
}

std::shared_ptr<Struct> GlobalContext::get_struct(std::shared_ptr<const Type> type) const {
    if(!type){
        return nullptr;
    }

    if(type->is_pointer()){
        type = type->data_type();
    }

    eddic_assert(type->is_custom_type() || type->is_template_type(), "This type has no corresponding struct");

    auto struct_name = type->mangle();
    return get_struct(struct_name);
}

int GlobalContext::member_offset(std::shared_ptr<const Struct> struct_, const std::string& member) const {
    int offset = 0;

    for(auto& m : struct_->members){
        if(m->name == member){
            return offset;
        }

        offset += m->type->size(platform);
    }

    eddic_unreachable("The member is not part of the struct");
}

std::shared_ptr<const Type> GlobalContext::member_type(std::shared_ptr<const Struct> struct_, int offset) const {
    int current_offset = 0;
    std::shared_ptr<Member> member = nullptr;

    for(auto& m : struct_->members){
        member = m;

        if(offset <= current_offset){
            return member->type;
        }

        current_offset += m->type->size(platform);
    }

    return member->type;
}

int GlobalContext::self_size_of_struct(std::shared_ptr<const Struct> struct_) const {
    int struct_size = 0;

    for(auto& m : struct_->members){
        struct_size += m->type->size(platform);
    }

    return struct_size;
}

int GlobalContext::total_size_of_struct(std::shared_ptr<const Struct> struct_) const {
   int total = self_size_of_struct(struct_);

   while(struct_->parent_type){
       struct_ = get_struct(struct_->parent_type);
       total += self_size_of_struct(struct_);
   }

   return total;
}

bool GlobalContext::is_recursively_nested(std::shared_ptr<const Struct> struct_, unsigned int left) const {
    if(left == 0){
        return true;
    }

    for(auto& m : struct_->members){
        auto type = m->type;

        if(type->is_structure()){
            if(is_recursively_nested(get_struct(type), left - 1)){
                return true;
            }
        }
    }

    return false;
}

bool GlobalContext::is_recursively_nested(std::shared_ptr<const Struct> struct_) const {
    return is_recursively_nested(struct_, 100);
}

void GlobalContext::addReference(const std::string& function){
    ++(getFunction(function).references());
}

void GlobalContext::removeReference(const std::string& function){
    --(getFunction(function).references());
}

int GlobalContext::referenceCount(const std::string& function){
    return getFunction(function).references();
}

void GlobalContext::addPrintFunction(const std::string& function, std::shared_ptr<const Type> parameterType){
    auto& printFunction = add_function(VOID, "print", function);
    printFunction.standard() = true;
    printFunction.parameters().emplace_back("a", parameterType);
}

void GlobalContext::defineStandardFunctions(){
    auto& printLineFunction = add_function(VOID, "print", "_F7println");
    printLineFunction.standard() = true;

    //print string
    addPrintFunction("_F5printS", STRING);
    addPrintFunction("_F7printlnS", STRING);

    //print integer
    addPrintFunction("_F5printI", INT);
    addPrintFunction("_F7printlnI", INT);

    //print char
    addPrintFunction("_F5printC", CHAR);
    addPrintFunction("_F7printlnC", CHAR);

    //print float
    addPrintFunction("_F5printF", FLOAT);
    addPrintFunction("_F7printlnF", FLOAT);

    auto& read_char_function = add_function(CHAR, "read_char", "_F9read_char");
    read_char_function.standard() = true;

    //alloc function
    auto& allocFunction = add_function(new_pointer_type(INT), "alloc", "_F5allocI");
    allocFunction.standard() = true;
    allocFunction.parameters().emplace_back("a", INT);

    //free function
    auto& freeFunction = add_function(VOID, "free", "_F4freePI");
    freeFunction.standard() = true;
    freeFunction.parameters().emplace_back("a", INT);

    //time function
    auto& timeFunction = add_function(VOID, "time", "_F4timeAI");
    timeFunction.standard() = true;
    timeFunction.parameters().emplace_back("a", new_array_type(INT));

    //duration function
    auto& durationFunction = add_function(VOID, "duration", "_F8durationAIAI");
    durationFunction.standard() = true;
    durationFunction.parameters().emplace_back("a", new_array_type(INT));
    durationFunction.parameters().emplace_back("b", new_array_type(INT));
}

const GlobalContext::FunctionMap& GlobalContext::functions() const {
    return m_functions;
}

Platform GlobalContext::target_platform() const {
    return platform;
}

statistics& GlobalContext::stats(){
    return m_statistics;
}
<|endoftext|>


<commit_before>#include "iotsa.h"
#include "iotsaCapabilities.h"
#include "iotsaConfigFile.h"
#include <ArduinoJWT.h>
#include <ArduinoJson.h>

#define IFDEBUGX if(1)

// Static method to check whether a string exactly matches a Json object,
// or is included in the Json object if it is an array.
static bool stringContainedIn(const char *wanted, JsonVariant& got) {
  if (got.is<char*>()) {
    return strcmp(wanted, got.as<const char *>()) == 0;
  }
  if (!got.is<JsonArray>()) {
    return false;
  }
  JsonArray& gotArray = got.as<JsonArray>();
  for(size_t i=0; i<gotArray.size(); i++) {
    const char *gotItem = gotArray[i];
    if (strcmp(gotItem, wanted) == 0) {
      return true;
    }
  }
  return false;
}

// Get a scope indicator from a JSON variant
static IotsaCapabilityObjectScope getRightFrom(const JsonVariant& arg) {
  if (!arg.is<char*>()) return IOTSA_SCOPE_NONE;
  const char *argStr = arg.as<char*>();
  if (strcmp(argStr, "self") == 0) return IOTSA_SCOPE_SELF;
  if (strcmp(argStr, "descendant-or-self") == 0) return IOTSA_SCOPE_FULL;
  if (strcmp(argStr, "descendant") == 0) return IOTSA_SCOPE_CHILD;
  if (strcmp(argStr, "child") == 0) return IOTSA_SCOPE_CHILD;
  return IOTSA_SCOPE_NONE;
}

bool IotsaCapability::allows(const char *_obj, IotsaApiOperation verb) {
  IotsaCapabilityObjectScope scope = scopes[int(verb)];
  int matchLength = obj.length();
  switch(scope) {
    case IOTSA_SCOPE_NONE:
      break;
    case IOTSA_SCOPE_SELF:
      if (strcmp(obj.c_str(), _obj) == 0)
        return true;
      break;
    case IOTSA_SCOPE_FULL:
      if (strncmp(obj.c_str(), _obj, matchLength) == 0) {
        char nextCh = _obj[matchLength];
        if (nextCh == '\0' || nextCh == '/')
          return true;
      }
      break;
    case IOTSA_SCOPE_CHILD:
      if (strncmp(obj.c_str(), _obj, matchLength) == 0) {
        char nextCh = _obj[matchLength];
        if (nextCh == '/')
          return true;
      }
      break;
  }
  // See if there is a next capabiliy we can check, otherwise we don't have permission.
  if (next) return next->allows(_obj, verb);
  return false;
}

IotsaCapabilityMod::IotsaCapabilityMod(IotsaApplication &_app, IotsaAuthenticationProvider& _chain)
:	IotsaAuthMod(_app),
  capabilities(NULL),
#ifdef IOTSA_WITH_API
  api(this, _app, this),
#endif
  chain(_chain),
  trustedIssuer(""),
  issuerKey("")
{
	configLoad();
}

#ifdef IOTSA_WITH_WEB
void
IotsaCapabilityMod::handler() {
  String _trustedIssuer = server->arg("trustedIssuer");
  String _issuerKey = server->arg("issuerKey");
  if (_trustedIssuer != "" || _issuerKey != "") {
    if (!iotsaConfig.inConfigurationMode()) {
      server->send(403, "text/plain", "403 Forbidden, not in configuration mode");
      return;
    }
    if (needsAuthentication("capabilities")) return;
    if (_trustedIssuer != "") trustedIssuer = _trustedIssuer;
    if (_issuerKey != "") issuerKey = _issuerKey;
    configSave();
    server->send(200, "text/plain", "ok\r\n");
    return;
  }
  String message = "<title>Capability Authority</title>
Capability Authority
";
  if (!iotsaConfig.inConfigurationMode())
    message += "
Note: You must be in configuration mode to be able to change issuer or key.
";
  message += "<form method='get'>Issuer: <input name='trustedIssuer' value='";
  message += htmlEncode(trustedIssuer);
  message += "'>
Current shared key is secret, but length is ";
  message += String(issuerKey.length());
  message += ".
New key: <input name='issuerKey'>
<input type='Submit'></form>";

  server->send(200, "text/html", message);
}

String IotsaCapabilityMod::info() {
  String message = "
Capabilities enabled.";
  message += " See /capabilities to change settings.";
  message += "
";
  return message;
}
#endif // IOTSA_WITH_WEB

#ifdef IOTSA_WITH_API
bool IotsaCapabilityMod::getHandler(const char *path, JsonObject& reply) {
  if (strcmp(path, "/api/capabilities") != 0) return false;
  reply["trustedIssuer"] = trustedIssuer;
  reply["has_issuerKey"] = (issuerKey.length() > 0);
  return true;
}

bool IotsaCapabilityMod::putHandler(const char *path, const JsonVariant& request, JsonObject& reply) {
  if (strcmp(path, "/api/capabilities") != 0) return false;
  if (!iotsaConfig.inConfigurationMode()) return false;
  bool anyChanged = false;
  JsonObject& reqObj = request.as<JsonObject>();
  if (reqObj.containsKey("trustedIssuer")) {
    trustedIssuer = reqObj.get<String>("trustedIssuer");
    anyChanged = true;
  }
  if (reqObj.containsKey("issuerKey")) {
    issuerKey = reqObj.get<String>("issuerKey");
    anyChanged = true;
  }
  if (anyChanged) {
    configSave();
  }
  return anyChanged;
}

bool IotsaCapabilityMod::postHandler(const char *path, const JsonVariant& request, JsonObject& reply) {
  return false;
}
#endif // IOTSA_WITH_API

void IotsaCapabilityMod::setup() {
  configLoad();
}

void IotsaCapabilityMod::serverSetup() {
#ifdef IOTSA_WITH_WEB
  server->on("/capabilities", std::bind(&IotsaCapabilityMod::handler, this));
#endif
#ifdef IOTSA_WITH_API
  api.setup("/api/capabilities", true, true, false);
  name = "capabilities";
#endif
}

void IotsaCapabilityMod::configLoad() {
  IotsaConfigFileLoad cf("/config/capabilities.cfg");
  cf.get("issuer", trustedIssuer, "");
  cf.get("key", issuerKey, "");
}

void IotsaCapabilityMod::configSave() {
  IotsaConfigFileSave cf("/config/capabilities.cfg");
  cf.put("issuer", trustedIssuer);
  cf.put("key", issuerKey);
  IotsaSerial.print("Saved capabilities.cfg, issuer=");
  IotsaSerial.print(trustedIssuer);
  IotsaSerial.print(", key length=");
  IotsaSerial.println(issuerKey.length());
}

void IotsaCapabilityMod::loop() {
}

bool IotsaCapabilityMod::allows(const char *obj, IotsaApiOperation verb) {
#ifdef IOTSA_WITH_HTTP_OR_HTTPS
  loadCapabilitiesFromRequest();
#endif
#ifdef IOTSA_WITH_COAP
  // Need to load capability from coap headers, somehow...
#endif
  if (capabilities) {
    if (capabilities->allows(obj, verb)) {
      IFDEBUGX IotsaSerial.print("Capability allows operation on ");
      IFDEBUGX IotsaSerial.println(obj);
      return true;
    }
    IFDEBUGX IotsaSerial.print("Capability does NOT allow operation on ");
    IFDEBUGX IotsaSerial.println(obj);
  }
  // If no rights fall back to username/password authentication
  return chain.allows(obj, verb);
}

bool IotsaCapabilityMod::allows(const char *right) {
  // If no rights fall back to username/password authentication
  return chain.allows(right);
}
#ifdef IOTSA_WITH_HTTP_OR_HTTPS
void IotsaCapabilityMod::loadCapabilitiesFromRequest() {

  // Free old capabilities
  IotsaCapability **cpp;
  for (cpp=&capabilities; *cpp; cpp=&(*cpp)->next) free(*cpp);
  capabilities = NULL;

  // Check that we can load and verify capabilities
  if (trustedIssuer == "" || issuerKey == "") return;

  // Load the bearer token from the request
  if (!server->hasHeader("Authorization")) {
    IFDEBUGX Serial.println("No authorization header in request");
    return;
  }
  String authHeader = server->header("Authorization");
  if (!authHeader.startsWith("Bearer ")) {
    IFDEBUGX Serial.println("No bearer token in request");
    return;
  }
  String token = authHeader.substring(7);

  // Decode the bearer token
  ArduinoJWT decoder(issuerKey);
  String payload;
  bool ok = decoder.decodeJWT(token, payload);
  // If decode returned false the token wasn't signed with the correct key.
  if (!ok) {
    IFDEBUGX IotsaSerial.println("Did not decode correctly with key");
    return;
  }
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(payload);

  // check that issuer matches
  String issuer = root["iss"];
  if (issuer != trustedIssuer) {
    IFDEBUGX IotsaSerial.print("Issuer did not match, wtd=");
    IFDEBUGX IotsaSerial.print(trustedIssuer);
    IFDEBUGX IotsaSerial.print(", got=");
    IFDEBUGX IotsaSerial.println(issuer);
    return;
  }

  if (root.containsKey("aud")) {
    JsonVariant audience = root["aud"];
    String myFullName = iotsaConfig.hostName + ".local";
#ifdef IOTSA_WITH_HTTPS
    String myUrl = "https://" + myFullName;
#else
    String myUrl = "http://" + myFullName;
#endif
    if (audience != "*" && audience != myFullName && audience != myUrl) {
      IFDEBUGX IotsaSerial.print("Audience did not match, wtd=");
      IFDEBUGX IotsaSerial.print(myFullName);
      IFDEBUGX IotsaSerial.print(", got=");
      IFDEBUGX IotsaSerial.println(audience.as<String>());
      return;
    }
  }
  const char *obj = root.get<char*>("obj");
  IotsaCapabilityObjectScope get = getRightFrom(root["get"]);
  IotsaCapabilityObjectScope put = getRightFrom(root["put"]);
  IotsaCapabilityObjectScope post = getRightFrom(root["post"]);
  IFDEBUGX IotsaSerial.print("capability for ");
  IFDEBUGX IotsaSerial.print(obj);
  IFDEBUGX IotsaSerial.print(", get=");
  IFDEBUGX IotsaSerial.print(int(get));
  IFDEBUGX IotsaSerial.print(", put=");
  IFDEBUGX IotsaSerial.print(int(put));
  IFDEBUGX IotsaSerial.print(", post=");
  IFDEBUGX IotsaSerial.print(int(post));
  IFDEBUGX IotsaSerial.println(" loaded");
  capabilities = new IotsaCapability(obj, get, put, post);
}
#endif // IOTSA_WITH_HTTP_OR_HTTPS<commit_msg>commented out unused static function<commit_after>#include "iotsa.h"
#include "iotsaCapabilities.h"
#include "iotsaConfigFile.h"
#include <ArduinoJWT.h>
#include <ArduinoJson.h>

#define IFDEBUGX if(1)

#if 0
// Static method to check whether a string exactly matches a Json object,
// or is included in the Json object if it is an array.
static bool stringContainedIn(const char *wanted, JsonVariant& got) {
  if (got.is<char*>()) {
    return strcmp(wanted, got.as<const char *>()) == 0;
  }
  if (!got.is<JsonArray>()) {
    return false;
  }
  JsonArray& gotArray = got.as<JsonArray>();
  for(size_t i=0; i<gotArray.size(); i++) {
    const char *gotItem = gotArray[i];
    if (strcmp(gotItem, wanted) == 0) {
      return true;
    }
  }
  return false;
}
#endif

// Get a scope indicator from a JSON variant
static IotsaCapabilityObjectScope getRightFrom(const JsonVariant& arg) {
  if (!arg.is<char*>()) return IOTSA_SCOPE_NONE;
  const char *argStr = arg.as<char*>();
  if (strcmp(argStr, "self") == 0) return IOTSA_SCOPE_SELF;
  if (strcmp(argStr, "descendant-or-self") == 0) return IOTSA_SCOPE_FULL;
  if (strcmp(argStr, "descendant") == 0) return IOTSA_SCOPE_CHILD;
  if (strcmp(argStr, "child") == 0) return IOTSA_SCOPE_CHILD;
  return IOTSA_SCOPE_NONE;
}

bool IotsaCapability::allows(const char *_obj, IotsaApiOperation verb) {
  IotsaCapabilityObjectScope scope = scopes[int(verb)];
  int matchLength = obj.length();
  switch(scope) {
    case IOTSA_SCOPE_NONE:
      break;
    case IOTSA_SCOPE_SELF:
      if (strcmp(obj.c_str(), _obj) == 0)
        return true;
      break;
    case IOTSA_SCOPE_FULL:
      if (strncmp(obj.c_str(), _obj, matchLength) == 0) {
        char nextCh = _obj[matchLength];
        if (nextCh == '\0' || nextCh == '/')
          return true;
      }
      break;
    case IOTSA_SCOPE_CHILD:
      if (strncmp(obj.c_str(), _obj, matchLength) == 0) {
        char nextCh = _obj[matchLength];
        if (nextCh == '/')
          return true;
      }
      break;
  }
  // See if there is a next capabiliy we can check, otherwise we don't have permission.
  if (next) return next->allows(_obj, verb);
  return false;
}

IotsaCapabilityMod::IotsaCapabilityMod(IotsaApplication &_app, IotsaAuthenticationProvider& _chain)
:	IotsaAuthMod(_app),
  capabilities(NULL),
#ifdef IOTSA_WITH_API
  api(this, _app, this),
#endif
  chain(_chain),
  trustedIssuer(""),
  issuerKey("")
{
	configLoad();
}

#ifdef IOTSA_WITH_WEB
void
IotsaCapabilityMod::handler() {
  String _trustedIssuer = server->arg("trustedIssuer");
  String _issuerKey = server->arg("issuerKey");
  if (_trustedIssuer != "" || _issuerKey != "") {
    if (!iotsaConfig.inConfigurationMode()) {
      server->send(403, "text/plain", "403 Forbidden, not in configuration mode");
      return;
    }
    if (needsAuthentication("capabilities")) return;
    if (_trustedIssuer != "") trustedIssuer = _trustedIssuer;
    if (_issuerKey != "") issuerKey = _issuerKey;
    configSave();
    server->send(200, "text/plain", "ok\r\n");
    return;
  }
  String message = "<title>Capability Authority</title>
Capability Authority
";
  if (!iotsaConfig.inConfigurationMode())
    message += "
Note: You must be in configuration mode to be able to change issuer or key.
";
  message += "<form method='get'>Issuer: <input name='trustedIssuer' value='";
  message += htmlEncode(trustedIssuer);
  message += "'>
Current shared key is secret, but length is ";
  message += String(issuerKey.length());
  message += ".
New key: <input name='issuerKey'>
<input type='Submit'></form>";

  server->send(200, "text/html", message);
}

String IotsaCapabilityMod::info() {
  String message = "
Capabilities enabled.";
  message += " See /capabilities to change settings.";
  message += "
";
  return message;
}
#endif // IOTSA_WITH_WEB

#ifdef IOTSA_WITH_API
bool IotsaCapabilityMod::getHandler(const char *path, JsonObject& reply) {
  if (strcmp(path, "/api/capabilities") != 0) return false;
  reply["trustedIssuer"] = trustedIssuer;
  reply["has_issuerKey"] = (issuerKey.length() > 0);
  return true;
}

bool IotsaCapabilityMod::putHandler(const char *path, const JsonVariant& request, JsonObject& reply) {
  if (strcmp(path, "/api/capabilities") != 0) return false;
  if (!iotsaConfig.inConfigurationMode()) return false;
  bool anyChanged = false;
  JsonObject& reqObj = request.as<JsonObject>();
  if (reqObj.containsKey("trustedIssuer")) {
    trustedIssuer = reqObj.get<String>("trustedIssuer");
    anyChanged = true;
  }
  if (reqObj.containsKey("issuerKey")) {
    issuerKey = reqObj.get<String>("issuerKey");
    anyChanged = true;
  }
  if (anyChanged) {
    configSave();
  }
  return anyChanged;
}

bool IotsaCapabilityMod::postHandler(const char *path, const JsonVariant& request, JsonObject& reply) {
  return false;
}
#endif // IOTSA_WITH_API

void IotsaCapabilityMod::setup() {
  configLoad();
}

void IotsaCapabilityMod::serverSetup() {
#ifdef IOTSA_WITH_WEB
  server->on("/capabilities", std::bind(&IotsaCapabilityMod::handler, this));
#endif
#ifdef IOTSA_WITH_API
  api.setup("/api/capabilities", true, true, false);
  name = "capabilities";
#endif
}

void IotsaCapabilityMod::configLoad() {
  IotsaConfigFileLoad cf("/config/capabilities.cfg");
  cf.get("issuer", trustedIssuer, "");
  cf.get("key", issuerKey, "");
}

void IotsaCapabilityMod::configSave() {
  IotsaConfigFileSave cf("/config/capabilities.cfg");
  cf.put("issuer", trustedIssuer);
  cf.put("key", issuerKey);
  IotsaSerial.print("Saved capabilities.cfg, issuer=");
  IotsaSerial.print(trustedIssuer);
  IotsaSerial.print(", key length=");
  IotsaSerial.println(issuerKey.length());
}

void IotsaCapabilityMod::loop() {
}

bool IotsaCapabilityMod::allows(const char *obj, IotsaApiOperation verb) {
#ifdef IOTSA_WITH_HTTP_OR_HTTPS
  loadCapabilitiesFromRequest();
#endif
#ifdef IOTSA_WITH_COAP
  // Need to load capability from coap headers, somehow...
#endif
  if (capabilities) {
    if (capabilities->allows(obj, verb)) {
      IFDEBUGX IotsaSerial.print("Capability allows operation on ");
      IFDEBUGX IotsaSerial.println(obj);
      return true;
    }
    IFDEBUGX IotsaSerial.print("Capability does NOT allow operation on ");
    IFDEBUGX IotsaSerial.println(obj);
  }
  // If no rights fall back to username/password authentication
  return chain.allows(obj, verb);
}

bool IotsaCapabilityMod::allows(const char *right) {
  // If no rights fall back to username/password authentication
  return chain.allows(right);
}
#ifdef IOTSA_WITH_HTTP_OR_HTTPS
void IotsaCapabilityMod::loadCapabilitiesFromRequest() {

  // Free old capabilities
  IotsaCapability **cpp;
  for (cpp=&capabilities; *cpp; cpp=&(*cpp)->next) free(*cpp);
  capabilities = NULL;

  // Check that we can load and verify capabilities
  if (trustedIssuer == "" || issuerKey == "") return;

  // Load the bearer token from the request
  if (!server->hasHeader("Authorization")) {
    IFDEBUGX Serial.println("No authorization header in request");
    return;
  }
  String authHeader = server->header("Authorization");
  if (!authHeader.startsWith("Bearer ")) {
    IFDEBUGX Serial.println("No bearer token in request");
    return;
  }
  String token = authHeader.substring(7);

  // Decode the bearer token
  ArduinoJWT decoder(issuerKey);
  String payload;
  bool ok = decoder.decodeJWT(token, payload);
  // If decode returned false the token wasn't signed with the correct key.
  if (!ok) {
    IFDEBUGX IotsaSerial.println("Did not decode correctly with key");
    return;
  }
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(payload);

  // check that issuer matches
  String issuer = root["iss"];
  if (issuer != trustedIssuer) {
    IFDEBUGX IotsaSerial.print("Issuer did not match, wtd=");
    IFDEBUGX IotsaSerial.print(trustedIssuer);
    IFDEBUGX IotsaSerial.print(", got=");
    IFDEBUGX IotsaSerial.println(issuer);
    return;
  }

  if (root.containsKey("aud")) {
    JsonVariant audience = root["aud"];
    String myFullName = iotsaConfig.hostName + ".local";
#ifdef IOTSA_WITH_HTTPS
    String myUrl = "https://" + myFullName;
#else
    String myUrl = "http://" + myFullName;
#endif
    if (audience != "*" && audience != myFullName && audience != myUrl) {
      IFDEBUGX IotsaSerial.print("Audience did not match, wtd=");
      IFDEBUGX IotsaSerial.print(myFullName);
      IFDEBUGX IotsaSerial.print(", got=");
      IFDEBUGX IotsaSerial.println(audience.as<String>());
      return;
    }
  }
  const char *obj = root.get<char*>("obj");
  IotsaCapabilityObjectScope get = getRightFrom(root["get"]);
  IotsaCapabilityObjectScope put = getRightFrom(root["put"]);
  IotsaCapabilityObjectScope post = getRightFrom(root["post"]);
  IFDEBUGX IotsaSerial.print("capability for ");
  IFDEBUGX IotsaSerial.print(obj);
  IFDEBUGX IotsaSerial.print(", get=");
  IFDEBUGX IotsaSerial.print(int(get));
  IFDEBUGX IotsaSerial.print(", put=");
  IFDEBUGX IotsaSerial.print(int(put));
  IFDEBUGX IotsaSerial.print(", post=");
  IFDEBUGX IotsaSerial.print(int(post));
  IFDEBUGX IotsaSerial.println(" loaded");
  capabilities = new IotsaCapability(obj, get, put, post);
}
#endif // IOTSA_WITH_HTTP_OR_HTTPS<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2012 J-P Nurmi <jpnurmi@gmail.com>
*
* This library 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 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include "ircmessagedecoder_p.h"
#include "irccodecplugin.h"
#include <QCoreApplication>
#include <QPluginLoader>
#include <QStringList>
#include <QDebug>
#include <QMap>
#include <QDir>

extern "C" {
    int IsUTF8Text(const char* utf8, int len);
}

typedef QMap<QByteArray, IrcCodecPlugin*> IrcCodecPluginMap;
Q_GLOBAL_STATIC(IrcCodecPluginMap, irc_codec_plugins)

static QByteArray irc_plugin_key = qgetenv("COMMUNI_CODEC_PLUGIN");

COMMUNI_EXPORT void irc_set_codec_plugin(const QByteArray& key)
{
    irc_plugin_key = key;
}

IrcMessageDecoder::IrcMessageDecoder()
{
    d.fallback = QTextCodec::codecForName("ISO-8859-15");
}

IrcMessageDecoder::~IrcMessageDecoder()
{
}

QByteArray IrcMessageDecoder::encoding() const
{
    return d.fallback->name();
}

void IrcMessageDecoder::setEncoding(const QByteArray& encoding)
{
    if (QTextCodec::availableCodecs().contains(encoding))
        d.fallback = QTextCodec::codecForName(encoding);
}

QString IrcMessageDecoder::decode(const QByteArray& data) const
{
    // TODO: not thread safe
    static QByteArray pluginKey;
    static bool initialized = false;
    if (!initialized) {
        pluginKey = const_cast<IrcMessageDecoder*>(this)->initialize();
        initialized = true;
    }

    QTextCodec* codec = 0;
    if (IsUTF8Text(data, data.length())) {
        codec = QTextCodec::codecForName("UTF-8");
    } else {
        QByteArray name = d.fallback->name();
        IrcCodecPlugin* plugin = irc_codec_plugins()->value(pluginKey);
        if (plugin)
            name = plugin->codecForData(data);
        codec = QTextCodec::codecForName(name);
    }

    if (!codec)
        codec = d.fallback;
    Q_ASSERT(codec);
    return codec->toUnicode(data);
}

QByteArray IrcMessageDecoder::initialize()
{
    bool loaded = loadPlugins();
    QByteArray pluginKey = irc_plugin_key;
    if (!pluginKey.isEmpty() && !irc_codec_plugins()->contains(pluginKey)) {
        qWarning() << "IrcMessageDecoder:" << pluginKey << "plugin not loaded";
        if (loaded)
            qWarning() << "IrcMessageDecoder: available plugins:" << irc_codec_plugins()->keys();
    }
    if (!loaded)
        qWarning() << "IrcMessageDecoder: no plugins available";

    if (pluginKey.isEmpty() && !irc_codec_plugins()->isEmpty())
        pluginKey = irc_codec_plugins()->keys().first();
    return pluginKey;
}

#if defined(Q_OS_WIN)
#define COMMUNI_PATH_SEPARATOR ';'
#else
#define COMMUNI_PATH_SEPARATOR ':'
#endif

static QStringList pluginPaths()
{
    QStringList paths = QCoreApplication::libraryPaths();
    const QByteArray env = qgetenv("COMMUNI_PLUGIN_PATH");
    if (!env.isEmpty()) {
        foreach(const QString & path, QFile::decodeName(env).split(COMMUNI_PATH_SEPARATOR, QString::SkipEmptyParts)) {
            QString canonicalPath = QDir(path).canonicalPath();
            if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
                paths += canonicalPath;
        }
    }
    return paths;
}

bool IrcMessageDecoder::loadPlugins()
{
    foreach(QObject* instance, QPluginLoader::staticInstances()) {
        IrcCodecPlugin* plugin = qobject_cast<IrcCodecPlugin*>(instance);
        if (plugin)
            irc_codec_plugins()->insert(plugin->key(), plugin);
    }

    foreach(const QString & path, pluginPaths()) {
        QDir dir(path);
        if (!dir.cd("communi"))
            continue;

        foreach(const QFileInfo & file, dir.entryInfoList(QDir::Files)) {
            QPluginLoader loader(file.absoluteFilePath());
            IrcCodecPlugin* plugin = qobject_cast<IrcCodecPlugin*>(loader.instance());
            if (plugin)
                irc_codec_plugins()->insert(plugin->key(), plugin);
        }
    }
    return !irc_codec_plugins()->isEmpty();
}
<commit_msg>IrcMessageDecoder: add some debug output (when COMMUNI_DEBUG=1)<commit_after>/*
* Copyright (C) 2008-2012 J-P Nurmi <jpnurmi@gmail.com>
*
* This library 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 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include "ircmessagedecoder_p.h"
#include "irccodecplugin.h"
#include <QCoreApplication>
#include <QPluginLoader>
#include <QStringList>
#include <QDebug>
#include <QMap>
#include <QDir>

extern "C" {
    int IsUTF8Text(const char* utf8, int len);
}

typedef QMap<QByteArray, IrcCodecPlugin*> IrcCodecPluginMap;
Q_GLOBAL_STATIC(IrcCodecPluginMap, irc_codec_plugins)

static QByteArray irc_plugin_key = qgetenv("COMMUNI_CODEC_PLUGIN");

COMMUNI_EXPORT void irc_set_codec_plugin(const QByteArray& key)
{
    irc_plugin_key = key;
}

IrcMessageDecoder::IrcMessageDecoder()
{
    d.fallback = QTextCodec::codecForName("ISO-8859-15");
}

IrcMessageDecoder::~IrcMessageDecoder()
{
}

QByteArray IrcMessageDecoder::encoding() const
{
    return d.fallback->name();
}

void IrcMessageDecoder::setEncoding(const QByteArray& encoding)
{
    if (QTextCodec::availableCodecs().contains(encoding))
        d.fallback = QTextCodec::codecForName(encoding);
}

QString IrcMessageDecoder::decode(const QByteArray& data) const
{
    // TODO: not thread safe
    static QByteArray pluginKey;
    static bool initialized = false;
    if (!initialized) {
        pluginKey = const_cast<IrcMessageDecoder*>(this)->initialize();
        initialized = true;
    }

    QTextCodec* codec = 0;
    if (IsUTF8Text(data, data.length())) {
        codec = QTextCodec::codecForName("UTF-8");
    } else {
        QByteArray name = d.fallback->name();
        IrcCodecPlugin* plugin = irc_codec_plugins()->value(pluginKey);
        if (plugin)
            name = plugin->codecForData(data);
        codec = QTextCodec::codecForName(name);
    }

    if (!codec)
        codec = d.fallback;
    Q_ASSERT(codec);
    return codec->toUnicode(data);
}

QByteArray IrcMessageDecoder::initialize()
{
    bool loaded = loadPlugins();
    QByteArray pluginKey = irc_plugin_key;
    if (!pluginKey.isEmpty() && !irc_codec_plugins()->contains(pluginKey)) {
        qWarning() << "IrcMessageDecoder:" << pluginKey << "plugin not loaded";
        if (loaded)
            qWarning() << "IrcMessageDecoder: available plugins:" << irc_codec_plugins()->keys();
    }
    if (!loaded)
        qWarning() << "IrcMessageDecoder: no plugins available";

    if (pluginKey.isEmpty() && !irc_codec_plugins()->isEmpty())
        pluginKey = irc_codec_plugins()->keys().first();
    return pluginKey;
}

#if defined(Q_OS_WIN)
#define COMMUNI_PATH_SEPARATOR ';'
#else
#define COMMUNI_PATH_SEPARATOR ':'
#endif

static QStringList pluginPaths()
{
    QStringList paths = QCoreApplication::libraryPaths();
    const QByteArray env = qgetenv("COMMUNI_PLUGIN_PATH");
    if (!env.isEmpty()) {
        foreach(const QString & path, QFile::decodeName(env).split(COMMUNI_PATH_SEPARATOR, QString::SkipEmptyParts)) {
            QString canonicalPath = QDir(path).canonicalPath();
            if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
                paths += canonicalPath;
        }
    }
    static bool dbg = qgetenv("COMMUNI_DEBUG").toInt();
    if (dbg) qDebug() << "IrcMessageDecoder: plugin paths:" << paths;
    return paths;
}

bool IrcMessageDecoder::loadPlugins()
{
    static bool dbg = qgetenv("COMMUNI_DEBUG").toInt();
    foreach(QObject* instance, QPluginLoader::staticInstances()) {
        IrcCodecPlugin* plugin = qobject_cast<IrcCodecPlugin*>(instance);
        if (plugin) {
            irc_codec_plugins()->insert(plugin->key(), plugin);
            if (dbg) qDebug() << "IrcMessageDecoder: loaded static plugin:" << plugin->key();
        }
    }

    foreach(const QString & path, pluginPaths()) {
        QDir dir(path);
        if (!dir.cd("communi"))
            continue;

        foreach(const QFileInfo & file, dir.entryInfoList(QDir::Files)) {
            QPluginLoader loader(file.absoluteFilePath());
            IrcCodecPlugin* plugin = qobject_cast<IrcCodecPlugin*>(loader.instance());
            if (plugin) {
                irc_codec_plugins()->insert(plugin->key(), plugin);
                if (dbg) qDebug() << "IrcMessageDecoder: loaded dynamic plugin:" << plugin->key() << file.fileName();
            }
        }
    }
    return !irc_codec_plugins()->isEmpty();
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_LAYER_TRAITS_HPP
#define DLL_LAYER_TRAITS_HPP

#include "tmp.hpp"
#include "decay_type.hpp"
#include "sparsity_method.hpp"

namespace dll {

template<typename Desc>
struct dyn_rbm;

template<typename Desc>
struct conv_rbm;

template<typename Desc>
struct conv_rbm_mp;

template<typename Desc>
struct mp_layer_3d;

template<typename Desc>
struct avgp_layer_3d;

/*!
 * \brief Type Traits to get information on RBM type
 */
template<typename RBM>
struct layer_traits {
    using rbm_t = RBM;

    /*!
     * \brief Indicates if the RBM is convolutional
     */
    static constexpr bool is_convolutional(){
        return cpp::is_specialization_of<conv_rbm, rbm_t>::value
            || cpp::is_specialization_of<conv_rbm_mp, rbm_t>::value;
    }

    /*!
     * \brief Indicates if this layer is a RBM layer.
     */
    static constexpr bool is_rbm_layer(){
        return !is_pooling_layer();
    }

    /*!
     * \brief Indicates if this layer is a pooling layer.
     */
    static constexpr bool is_pooling_layer(){
        return cpp::is_specialization_of<mp_layer_3d, rbm_t>::value
            || cpp::is_specialization_of<avgp_layer_3d, rbm_t>::value;
    }

    template<cpp_enable_if_cst(layer_traits<rbm_t>::is_rbm_layer())>
    static constexpr bool pretrain_last(){
        //Softmax unit should not be pretrained
        return rbm_t::hidden_unit != unit_type::SOFTMAX;
    }

    template<cpp_disable_if_cst(layer_traits<rbm_t>::is_rbm_layer())>
    static constexpr bool pretrain_last(){
        //if the pooling layer is the last, we spare the time to activate the previous layer by not training it
        //since training pooling layer is a nop, that doesn't change anything
        return false;
    }

    /*!
     * \brief Indicates if the RBM is dynamic
     */
    static constexpr bool is_dynamic(){
        return cpp::is_specialization_of<dyn_rbm, rbm_t>::value;
    }

    /*!
     * \brief Indicates if the RBM is convolutional and has probabilistic max
     * pooling
     */
    static constexpr bool has_probabilistic_max_pooling(){
        return cpp::is_specialization_of<conv_rbm_mp, rbm_t>::value;
    }

    static constexpr std::size_t input_size(){
        return rbm_t::input_size();
    }

    static constexpr std::size_t output_size(){
        return rbm_t::output_size();
    }

    static constexpr std::size_t batch_size(){
        return detail::get_value_l<dll::batch_size<1>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr bool has_momentum(){
        return rbm_t::desc::parameters::template contains<momentum>();
    }

    static constexpr bool is_parallel(){
        return rbm_t::desc::parameters::template contains<parallel>();
    }

    static constexpr bool is_verbose(){
        return rbm_t::desc::parameters::template contains<verbose>();
    }

    static constexpr bool has_shuffle(){
        return rbm_t::desc::parameters::template contains<shuffle>();
    }

    static constexpr bool is_dbn_only(){
        return rbm_t::desc::parameters::template contains<dbn_only>();
    }

    static constexpr bool is_memory(){
        return rbm_t::desc::parameters::template contains<memory>();
    }

    static constexpr bool has_sparsity(){
        return sparsity_method() != dll::sparsity_method::NONE;
    }

    static constexpr dll::sparsity_method sparsity_method(){
        return detail::get_value_l<sparsity<dll::sparsity_method::NONE>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr enum dll::bias_mode bias_mode(){
        return detail::get_value_l<bias<dll::bias_mode::SIMPLE>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr decay_type decay(){
        return detail::get_value_l<weight_decay<decay_type::NONE>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr bool init_weights(){
        return rbm_t::desc::parameters::template contains<dll::init_weights>();
    }

    static constexpr bool free_energy(){
        return rbm_t::desc::parameters::template contains<dll::free_energy>();
    }
};

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t get_batch_size(const RBM& rbm){
    return rbm.batch_size;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t get_batch_size(const RBM&){
    return layer_traits<RBM>::batch_size();
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t num_visible(const RBM& rbm){
    return rbm.num_visible;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t num_visible(const RBM&){
    return RBM::desc::num_visible;
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t num_hidden(const RBM& rbm){
    return rbm.num_hidden;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t num_hidden(const RBM&){
    return RBM::desc::num_hidden;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t output_size(const RBM&){
    return layer_traits<RBM>::output_size();
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t output_size(const RBM& rbm){
    return rbm.num_hidden;
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t input_size(const RBM& rbm){
    return rbm.num_visible;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t input_size(const RBM&){
    return layer_traits<RBM>::input_size();
}

} //end of dll namespace

#endif
<commit_msg>New traits: is_transform_layer<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_LAYER_TRAITS_HPP
#define DLL_LAYER_TRAITS_HPP

#include "tmp.hpp"
#include "decay_type.hpp"
#include "sparsity_method.hpp"

namespace dll {

template<typename Desc>
struct dyn_rbm;

template<typename Desc>
struct conv_rbm;

template<typename Desc>
struct conv_rbm_mp;

template<typename Desc>
struct mp_layer_3d;

template<typename Desc>
struct avgp_layer_3d;

template<typename Desc>
struct binarize_layer;

/*!
 * \brief Type Traits to get information on RBM type
 */
template<typename RBM>
struct layer_traits {
    using rbm_t = RBM;

    /*!
     * \brief Indicates if the RBM is convolutional
     */
    static constexpr bool is_convolutional(){
        return cpp::is_specialization_of<conv_rbm, rbm_t>::value
            || cpp::is_specialization_of<conv_rbm_mp, rbm_t>::value;
    }

    /*!
     * \brief Indicates if this layer is a RBM layer.
     */
    static constexpr bool is_rbm_layer(){
        return !(is_pooling_layer() || is_transform_layer());
    }

    /*!
     * \brief Indicates if this layer is a pooling layer.
     */
    static constexpr bool is_pooling_layer(){
        return cpp::is_specialization_of<mp_layer_3d, rbm_t>::value
            || cpp::is_specialization_of<avgp_layer_3d, rbm_t>::value;
    }

    /*!
     * \brief Indicates if this layer is a transformation layer.
     */
    static constexpr bool is_transform_layer(){
        return cpp::is_specialization_of<binarize_layer, rbm_t>::value;
    }

    /*!
     * \brief Indicates if this layer should be trained if it is the last layer.
     */
    template<cpp_enable_if_cst(layer_traits<rbm_t>::is_rbm_layer())>
    static constexpr bool pretrain_last(){
        //Softmax unit should not be pretrained
        return rbm_t::hidden_unit != unit_type::SOFTMAX;
    }

    template<cpp_disable_if_cst(layer_traits<rbm_t>::is_rbm_layer())>
    static constexpr bool pretrain_last(){
        //if the pooling layer is the last, we spare the time to activate the previous layer by not training it
        //since training pooling layer is a nop, that doesn't change anything
        return false;
    }

    /*!
     * \brief Indicates if the RBM is dynamic
     */
    static constexpr bool is_dynamic(){
        return cpp::is_specialization_of<dyn_rbm, rbm_t>::value;
    }

    /*!
     * \brief Indicates if the RBM is convolutional and has probabilistic max
     * pooling
     */
    static constexpr bool has_probabilistic_max_pooling(){
        return cpp::is_specialization_of<conv_rbm_mp, rbm_t>::value;
    }

    static constexpr std::size_t input_size(){
        return rbm_t::input_size();
    }

    static constexpr std::size_t output_size(){
        return rbm_t::output_size();
    }

    static constexpr std::size_t batch_size(){
        return detail::get_value_l<dll::batch_size<1>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr bool has_momentum(){
        return rbm_t::desc::parameters::template contains<momentum>();
    }

    static constexpr bool is_parallel(){
        return rbm_t::desc::parameters::template contains<parallel>();
    }

    static constexpr bool is_verbose(){
        return rbm_t::desc::parameters::template contains<verbose>();
    }

    static constexpr bool has_shuffle(){
        return rbm_t::desc::parameters::template contains<shuffle>();
    }

    static constexpr bool is_dbn_only(){
        return rbm_t::desc::parameters::template contains<dbn_only>();
    }

    static constexpr bool is_memory(){
        return rbm_t::desc::parameters::template contains<memory>();
    }

    static constexpr bool has_sparsity(){
        return sparsity_method() != dll::sparsity_method::NONE;
    }

    static constexpr dll::sparsity_method sparsity_method(){
        return detail::get_value_l<sparsity<dll::sparsity_method::NONE>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr enum dll::bias_mode bias_mode(){
        return detail::get_value_l<bias<dll::bias_mode::SIMPLE>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr decay_type decay(){
        return detail::get_value_l<weight_decay<decay_type::NONE>, typename rbm_t::desc::parameters>::value;
    }

    static constexpr bool init_weights(){
        return rbm_t::desc::parameters::template contains<dll::init_weights>();
    }

    static constexpr bool free_energy(){
        return rbm_t::desc::parameters::template contains<dll::free_energy>();
    }
};

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t get_batch_size(const RBM& rbm){
    return rbm.batch_size;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t get_batch_size(const RBM&){
    return layer_traits<RBM>::batch_size();
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t num_visible(const RBM& rbm){
    return rbm.num_visible;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t num_visible(const RBM&){
    return RBM::desc::num_visible;
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t num_hidden(const RBM& rbm){
    return rbm.num_hidden;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t num_hidden(const RBM&){
    return RBM::desc::num_hidden;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t output_size(const RBM&){
    return layer_traits<RBM>::output_size();
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t output_size(const RBM& rbm){
    return rbm.num_hidden;
}

template<typename RBM, cpp::enable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
std::size_t input_size(const RBM& rbm){
    return rbm.num_visible;
}

template<typename RBM, cpp::disable_if_u<layer_traits<RBM>::is_dynamic()> = cpp::detail::dummy>
constexpr std::size_t input_size(const RBM&){
    return layer_traits<RBM>::input_size();
}

} //end of dll namespace

#endif
<|endoftext|>


<commit_before>// Copyright 2015, Christopher J. Foster and the other displaz contributors.
// Use of this code is governed by the BSD-style license found in LICENSE.txt

#include "HookFormatter.h"

#include "IpcChannel.h"
#include "PointViewerMainWindow.h"

HookFormatter::HookFormatter(PointViewerMainWindow* getPayload, QByteArray hookSpec,
                                       QByteArray hookPayload, QObject* parent)
    : QObject(parent),
    m_hookSpec(hookSpec),
    m_hookPayload(hookPayload),
    m_getPayload(getPayload)
{
    connect(this, SIGNAL(sendIpcMessage(QByteArray)), parent, SLOT(sendMessage(QByteArray)));
    connect(parent, SIGNAL(disconnected()), this, SLOT(channelDisconnected()));
}

/// Get payload and dispatch signal to IpcChannel
void HookFormatter::hookActivated()
{
    QByteArray hookPayload = m_getPayload->hookPayload(m_hookPayload);
    QByteArray message = m_hookSpec + " " + hookPayload + "\n";

    emit sendIpcMessage(message);
}
<commit_msg>Resolve Coverity UMR - HookFormatter::m_eventId uninitialised<commit_after>// Copyright 2015, Christopher J. Foster and the other displaz contributors.
// Use of this code is governed by the BSD-style license found in LICENSE.txt

#include "HookFormatter.h"

#include "IpcChannel.h"
#include "PointViewerMainWindow.h"

HookFormatter::HookFormatter(PointViewerMainWindow* getPayload, QByteArray hookSpec,
                                       QByteArray hookPayload, QObject* parent)
    : QObject(parent),
    m_hookSpec(hookSpec),
    m_hookPayload(hookPayload),
    m_getPayload(getPayload),
    m_eventId(0)
{
    connect(this, SIGNAL(sendIpcMessage(QByteArray)), parent, SLOT(sendMessage(QByteArray)));
    connect(parent, SIGNAL(disconnected()), this, SLOT(channelDisconnected()));
}

/// Get payload and dispatch signal to IpcChannel
void HookFormatter::hookActivated()
{
    QByteArray hookPayload = m_getPayload->hookPayload(m_hookPayload);
    QByteArray message = m_hookSpec + " " + hookPayload + "\n";

    emit sendIpcMessage(message);
}
<|endoftext|>


<commit_before>//https://code.google.com/p/nya-engine/

#include "log.h"
#include "stdout_log.h"

namespace nya_log
{

namespace { log_base *default_log=0; }

log_base &no_log()
{
    static log_base l;
    return l;
}

void set_log(log_base *l)
{
    default_log=l;
}

log_base &log(const char *tag)
{
    if(!tag)
        tag="general";

    if(!default_log)
    {
        static stdout_log stdlog;
        stdlog.set_tag(tag);
        return stdlog;
    }

    default_log->set_tag(tag);
    return *default_log;
}

}
<commit_msg>fixed no_log because static variables destructs in uncontrollable order<commit_after>//https://code.google.com/p/nya-engine/

#include "log.h"
#include "stdout_log.h"

namespace nya_log
{

namespace { log_base *default_log=0; }

log_base &no_log()
{
    static log_base *l=new log_base();
    return *l;
}

void set_log(log_base *l) { default_log=l; }

log_base &log(const char *tag)
{
    if(!tag)
        tag="general";

    if(!default_log)
    {
        static stdout_log stdlog;
        stdlog.set_tag(tag);
        return stdlog;
    }

    default_log->set_tag(tag);
    return *default_log;
}

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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.
*/

#include "SceneGraphManager.h"
#include "SceneGraph.h"

namespace crown
{

//-----------------------------------------------------------------------------
SceneGraphManager::SceneGraphManager()
	: m_graphs(default_allocator())
{
}

//-----------------------------------------------------------------------------
SceneGraphManager::~SceneGraphManager()
{
}

//-----------------------------------------------------------------------------
SceneGraph* SceneGraphManager::create_scene_graph()
{
	uint32_t index = m_graphs.size();
	SceneGraph* sg = CE_NEW(default_allocator(), SceneGraph)(index);
	m_graphs.push_back(sg);
	return sg;
}

//-----------------------------------------------------------------------------
void SceneGraphManager::destroy_scene_graph(SceneGraph* sg)
{
	CE_ASSERT_NOT_NULL(sg);

	m_graphs[sg->m_index] = m_graphs[m_graphs.size() - 1];
	m_graphs.pop_back();

	CE_DELETE(default_allocator(), sg);
}

//-----------------------------------------------------------------------------
void SceneGraphManager::update()
{
	for (uint32_t i = 0; i < m_graphs.size(); i++)
	{
		m_graphs[i]->update();
	}
}

} // namespace crown
<commit_msg>Fix destroying scene graphs<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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.
*/

#include "SceneGraphManager.h"
#include "SceneGraph.h"

namespace crown
{

//-----------------------------------------------------------------------------
SceneGraphManager::SceneGraphManager()
	: m_graphs(default_allocator())
{
}

//-----------------------------------------------------------------------------
SceneGraphManager::~SceneGraphManager()
{
}

//-----------------------------------------------------------------------------
SceneGraph* SceneGraphManager::create_scene_graph()
{
	uint32_t index = m_graphs.size();
	SceneGraph* sg = CE_NEW(default_allocator(), SceneGraph)(index);
	m_graphs.push_back(sg);
	return sg;
}

//-----------------------------------------------------------------------------
void SceneGraphManager::destroy_scene_graph(SceneGraph* sg)
{
	CE_ASSERT_NOT_NULL(sg);

	m_graphs[sg->m_index] = m_graphs[m_graphs.size() - 1];
	m_graphs[sg->m_index]->m_index = sg->m_index;
	m_graphs.pop_back();

	CE_DELETE(default_allocator(), sg);
}

//-----------------------------------------------------------------------------
void SceneGraphManager::update()
{
	for (uint32_t i = 0; i < m_graphs.size(); i++)
	{
		m_graphs[i]->update();
	}
}

} // namespace crown
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2009 Torus Knot Software Ltd

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.
-----------------------------------------------------------------------------
*/

#include "OgreGLESPixelFormat.h"

#include "OgreRoot.h"
#include "OgreRenderSystem.h"
#include "OgreBitwise.h"

namespace Ogre  {
    GLenum GLESPixelUtil::getGLOriginFormat(PixelFormat mFormat)
    {
        switch (mFormat)
        {
            case PF_A8:
                return GL_ALPHA;

            case PF_L8:
            case PF_L16:
            case PF_FLOAT16_R:
            case PF_FLOAT32_R:
                return GL_LUMINANCE;

            case PF_BYTE_LA:
            case PF_SHORT_GR:
            case PF_FLOAT16_GR:
            case PF_FLOAT32_GR:
                return GL_LUMINANCE_ALPHA;

            // PVR compressed formats
            case PF_PVR_RGB2:
                return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
            case PF_PVR_RGB4:
                return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
            case PF_PVR_RGBA2:
                return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
            case PF_PVR_RGBA4:
                return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;

            case PF_R3G3B2:
            case PF_R5G6B5:
            case PF_FLOAT16_RGB:
            case PF_FLOAT32_RGB:
            case PF_SHORT_RGB:
                return GL_RGB;

            case PF_X8R8G8B8:
            case PF_A8R8G8B8:
            case PF_B8G8R8A8:
            case PF_A1R5G5B5:
            case PF_A4R4G4B4:
            case PF_A2R10G10B10:
// This case in incorrect, swaps R & B channels
//                return GL_BGRA;

            case PF_X8B8G8R8:
            case PF_A8B8G8R8:
            case PF_A2B10G10R10:
            case PF_FLOAT16_RGBA:
            case PF_FLOAT32_RGBA:
            case PF_SHORT_RGBA:
                return GL_RGBA;

#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
            // Formats are in native endian, so R8G8B8 on little endian is
            // BGR, on big endian it is RGB.
            case PF_R8G8B8:
                return GL_RGB;
            case PF_B8G8R8:
                return 0;
#else
            case PF_R8G8B8:
                return 0;
            case PF_B8G8R8:
                return GL_RGB;
#endif
            case PF_DXT1:
            case PF_DXT3:
            case PF_DXT5:
            case PF_B5G6R5:
            default:
                return 0;
        }
    }

    GLenum GLESPixelUtil::getGLOriginDataType(PixelFormat mFormat)
    {
        switch (mFormat)
        {
            case PF_A8:
            case PF_L8:
            case PF_R8G8B8:
            case PF_B8G8R8:
            case PF_BYTE_LA:
            case PF_PVR_RGB2:
            case PF_PVR_RGB4:
            case PF_PVR_RGBA2:
            case PF_PVR_RGBA4:
                return GL_UNSIGNED_BYTE;
            case PF_R5G6B5:
            case PF_B5G6R5:
                return GL_UNSIGNED_SHORT_5_6_5;
            case PF_L16:
                return GL_UNSIGNED_SHORT;

#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
            case PF_X8B8G8R8:
            case PF_A8B8G8R8:
                return GL_UNSIGNED_INT_8_8_8_8_REV;
            case PF_X8R8G8B8:
            case PF_A8R8G8B8:
                return GL_UNSIGNED_INT_8_8_8_8_REV;
            case PF_B8G8R8A8:
                return GL_UNSIGNED_BYTE;
            case PF_R8G8B8A8:
                return GL_UNSIGNED_BYTE;
#else
            case PF_X8B8G8R8:
            case PF_A8B8G8R8:
            case PF_X8R8G8B8:
            case PF_A8R8G8B8:
                return GL_UNSIGNED_BYTE;
            case PF_B8G8R8A8:
            case PF_R8G8B8A8:
                return 0;
#endif

            case PF_FLOAT32_R:
            case PF_FLOAT32_GR:
            case PF_FLOAT32_RGB:
            case PF_FLOAT32_RGBA:
                return GL_FLOAT;
            case PF_SHORT_RGBA:
            case PF_SHORT_RGB:
            case PF_SHORT_GR:
                return GL_UNSIGNED_SHORT;

            case PF_A2R10G10B10:
            case PF_A2B10G10R10:
            case PF_FLOAT16_R:
            case PF_FLOAT16_GR:
            case PF_FLOAT16_RGB:
            case PF_FLOAT16_RGBA:
            case PF_R3G3B2:
            case PF_A1R5G5B5:
            case PF_A4R4G4B4:
                // TODO not supported
            default:
                return 0;
        }
    }

    GLenum GLESPixelUtil::getGLInternalFormat(PixelFormat fmt, bool hwGamma)
    {
        switch (fmt)
        {
            case PF_L8:
                return GL_LUMINANCE;

            case PF_A8:
                return GL_ALPHA;

            case PF_BYTE_LA:
                return GL_LUMINANCE_ALPHA;

            case PF_PVR_RGB2:
                return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
            case PF_PVR_RGB4:
                return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
            case PF_PVR_RGBA2:
                return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
            case PF_PVR_RGBA4:
                return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;

            case PF_R8G8B8:
            case PF_B8G8R8:
            case PF_X8B8G8R8:
            case PF_X8R8G8B8:
                // DJR - Commenting this out resolves texture problems on iPhone
//                if (!hwGamma)
//                {
//                    return GL_RGB;
//                }
            case PF_A8R8G8B8:
            case PF_B8G8R8A8:
                if (!hwGamma)
                {
                    return GL_RGBA;
                }
            case PF_A4L4:
            case PF_L16:
            case PF_A4R4G4B4:
            case PF_R3G3B2:
            case PF_A1R5G5B5:
            case PF_R5G6B5:
            case PF_B5G6R5:
            case PF_A2R10G10B10:
            case PF_A2B10G10R10:
            case PF_FLOAT16_R:
            case PF_FLOAT16_RGB:
            case PF_FLOAT16_GR:
            case PF_FLOAT16_RGBA:
            case PF_FLOAT32_R:
            case PF_FLOAT32_GR:
            case PF_FLOAT32_RGB:
            case PF_FLOAT32_RGBA:
            case PF_SHORT_RGBA:
            case PF_SHORT_RGB:
            case PF_SHORT_GR:
            case PF_DXT1:
            case PF_DXT3:
            case PF_DXT5:
            default:
                return 0;
        }
    }

    GLenum GLESPixelUtil::getClosestGLInternalFormat(PixelFormat mFormat,
                                                   bool hwGamma)
    {
        GLenum format = getGLInternalFormat(mFormat, hwGamma);
        if (format==0)
        {
            if (hwGamma)
            {
                // TODO not supported
                return 0;
            }
            else
            {
                return GL_RGBA;
            }
        }
        else
        {
            return format;
        }
    }

    PixelFormat GLESPixelUtil::getClosestOGREFormat(GLenum fmt)
    {
        switch (fmt)
        {
            case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
                return PF_PVR_RGB2;
            case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
                return PF_PVR_RGBA2;
            case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
                return PF_PVR_RGB4;
            case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
                return PF_PVR_RGBA4;
            case GL_LUMINANCE:
                return PF_L8;
            case GL_ALPHA:
                return PF_A8;
            case GL_LUMINANCE_ALPHA:
                return PF_BYTE_LA;
            case GL_RGB:
                return PF_X8R8G8B8;
            case GL_RGBA:
                return PF_A8R8G8B8;
#ifdef GL_BGRA
            case GL_BGRA:
#endif
//                return PF_X8B8G8R8;
            default:
                //TODO: not supported
                return PF_A8R8G8B8;
        };
    }

    size_t GLESPixelUtil::getMaxMipmaps(size_t width, size_t height, size_t depth,
                                      PixelFormat format)
    {
        size_t count = 0;

        do {
            if (width > 1)
            {
                width = width / 2;
            }
            if (height > 1)
            {
                height = height / 2;
            }
            if (depth > 1)
            {
                depth = depth / 2;
            }
            /*
            NOT needed, compressed formats will have mipmaps up to 1x1
            if(PixelUtil::isValidExtent(width, height, depth, format))
                count ++;
            else
                break;
            */
            count++;
        } while (!(width == 1 && height == 1 && depth == 1));

        return count;
    }

    size_t GLESPixelUtil::optionalPO2(size_t value)
    {
        const RenderSystemCapabilities *caps =
            Root::getSingleton().getRenderSystem()->getCapabilities();

        if (caps->hasCapability(RSC_NON_POWER_OF_2_TEXTURES))
        {
            return value;
        }
        else
        {
            return Bitwise::firstPO2From((uint32)value);
        }
    }

    PixelBox* GLESPixelUtil::convertToGLformat(const PixelBox &data,
                                             GLenum *outputFormat)
    {
        GLenum glFormat = GLESPixelUtil::getGLOriginFormat(data.format);
        if (glFormat != 0)
        {
            // format already supported
            return OGRE_NEW PixelBox(data);
        }

        PixelBox *converted = 0;

        if (data.format == PF_R8G8B8)
        {
            // Convert BGR -> RGB
            converted->format = PF_B8G8R8;
            *outputFormat = GL_RGB;

            converted = OGRE_NEW PixelBox(data);
            uint32 *data = (uint32 *) converted->data;
            for (uint i = 0; i < converted->getWidth() * converted->getHeight(); i++)
            {
                uint32 *color = data;
                *color = (*color & 0x000000ff) << 16 |
                         (*color & 0x0000FF00) |
                         (*color & 0x00FF0000) >> 16;
                data += 1;
            }
        }

        return converted;
    }
}
<commit_msg>Didn't mean to check this in, PVR texture support isn't finished yet.  Commenting it out for now<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2009 Torus Knot Software Ltd

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.
-----------------------------------------------------------------------------
*/

#include "OgreGLESPixelFormat.h"

#include "OgreRoot.h"
#include "OgreRenderSystem.h"
#include "OgreBitwise.h"

namespace Ogre  {
    GLenum GLESPixelUtil::getGLOriginFormat(PixelFormat mFormat)
    {
        switch (mFormat)
        {
            case PF_A8:
                return GL_ALPHA;

            case PF_L8:
            case PF_L16:
            case PF_FLOAT16_R:
            case PF_FLOAT32_R:
                return GL_LUMINANCE;

            case PF_BYTE_LA:
            case PF_SHORT_GR:
            case PF_FLOAT16_GR:
            case PF_FLOAT32_GR:
                return GL_LUMINANCE_ALPHA;

            // PVR compressed formats
//            case PF_PVR_RGB2:
//                return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
//            case PF_PVR_RGB4:
//                return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
//            case PF_PVR_RGBA2:
//                return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
//            case PF_PVR_RGBA4:
//                return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;

            case PF_R3G3B2:
            case PF_R5G6B5:
            case PF_FLOAT16_RGB:
            case PF_FLOAT32_RGB:
            case PF_SHORT_RGB:
                return GL_RGB;

            case PF_X8R8G8B8:
            case PF_A8R8G8B8:
            case PF_B8G8R8A8:
            case PF_A1R5G5B5:
            case PF_A4R4G4B4:
            case PF_A2R10G10B10:
// This case in incorrect, swaps R & B channels
//                return GL_BGRA;

            case PF_X8B8G8R8:
            case PF_A8B8G8R8:
            case PF_A2B10G10R10:
            case PF_FLOAT16_RGBA:
            case PF_FLOAT32_RGBA:
            case PF_SHORT_RGBA:
                return GL_RGBA;

#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
            // Formats are in native endian, so R8G8B8 on little endian is
            // BGR, on big endian it is RGB.
            case PF_R8G8B8:
                return GL_RGB;
            case PF_B8G8R8:
                return 0;
#else
            case PF_R8G8B8:
                return 0;
            case PF_B8G8R8:
                return GL_RGB;
#endif
            case PF_DXT1:
            case PF_DXT3:
            case PF_DXT5:
            case PF_B5G6R5:
            default:
                return 0;
        }
    }

    GLenum GLESPixelUtil::getGLOriginDataType(PixelFormat mFormat)
    {
        switch (mFormat)
        {
            case PF_A8:
            case PF_L8:
            case PF_R8G8B8:
            case PF_B8G8R8:
            case PF_BYTE_LA:
//            case PF_PVR_RGB2:
//            case PF_PVR_RGB4:
//            case PF_PVR_RGBA2:
//            case PF_PVR_RGBA4:
                return GL_UNSIGNED_BYTE;
            case PF_R5G6B5:
            case PF_B5G6R5:
                return GL_UNSIGNED_SHORT_5_6_5;
            case PF_L16:
                return GL_UNSIGNED_SHORT;

#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
            case PF_X8B8G8R8:
            case PF_A8B8G8R8:
                return GL_UNSIGNED_INT_8_8_8_8_REV;
            case PF_X8R8G8B8:
            case PF_A8R8G8B8:
                return GL_UNSIGNED_INT_8_8_8_8_REV;
            case PF_B8G8R8A8:
                return GL_UNSIGNED_BYTE;
            case PF_R8G8B8A8:
                return GL_UNSIGNED_BYTE;
#else
            case PF_X8B8G8R8:
            case PF_A8B8G8R8:
            case PF_X8R8G8B8:
            case PF_A8R8G8B8:
                return GL_UNSIGNED_BYTE;
            case PF_B8G8R8A8:
            case PF_R8G8B8A8:
                return 0;
#endif

            case PF_FLOAT32_R:
            case PF_FLOAT32_GR:
            case PF_FLOAT32_RGB:
            case PF_FLOAT32_RGBA:
                return GL_FLOAT;
            case PF_SHORT_RGBA:
            case PF_SHORT_RGB:
            case PF_SHORT_GR:
                return GL_UNSIGNED_SHORT;

            case PF_A2R10G10B10:
            case PF_A2B10G10R10:
            case PF_FLOAT16_R:
            case PF_FLOAT16_GR:
            case PF_FLOAT16_RGB:
            case PF_FLOAT16_RGBA:
            case PF_R3G3B2:
            case PF_A1R5G5B5:
            case PF_A4R4G4B4:
                // TODO not supported
            default:
                return 0;
        }
    }

    GLenum GLESPixelUtil::getGLInternalFormat(PixelFormat fmt, bool hwGamma)
    {
        switch (fmt)
        {
            case PF_L8:
                return GL_LUMINANCE;

            case PF_A8:
                return GL_ALPHA;

            case PF_BYTE_LA:
                return GL_LUMINANCE_ALPHA;

//            case PF_PVR_RGB2:
//                return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
//            case PF_PVR_RGB4:
//                return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
//            case PF_PVR_RGBA2:
//                return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
//            case PF_PVR_RGBA4:
//                return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;

            case PF_R8G8B8:
            case PF_B8G8R8:
            case PF_X8B8G8R8:
            case PF_X8R8G8B8:
                // DJR - Commenting this out resolves texture problems on iPhone
//                if (!hwGamma)
//                {
//                    return GL_RGB;
//                }
            case PF_A8R8G8B8:
            case PF_B8G8R8A8:
                if (!hwGamma)
                {
                    return GL_RGBA;
                }
            case PF_A4L4:
            case PF_L16:
            case PF_A4R4G4B4:
            case PF_R3G3B2:
            case PF_A1R5G5B5:
            case PF_R5G6B5:
            case PF_B5G6R5:
            case PF_A2R10G10B10:
            case PF_A2B10G10R10:
            case PF_FLOAT16_R:
            case PF_FLOAT16_RGB:
            case PF_FLOAT16_GR:
            case PF_FLOAT16_RGBA:
            case PF_FLOAT32_R:
            case PF_FLOAT32_GR:
            case PF_FLOAT32_RGB:
            case PF_FLOAT32_RGBA:
            case PF_SHORT_RGBA:
            case PF_SHORT_RGB:
            case PF_SHORT_GR:
            case PF_DXT1:
            case PF_DXT3:
            case PF_DXT5:
            default:
                return 0;
        }
    }

    GLenum GLESPixelUtil::getClosestGLInternalFormat(PixelFormat mFormat,
                                                   bool hwGamma)
    {
        GLenum format = getGLInternalFormat(mFormat, hwGamma);
        if (format==0)
        {
            if (hwGamma)
            {
                // TODO not supported
                return 0;
            }
            else
            {
                return GL_RGBA;
            }
        }
        else
        {
            return format;
        }
    }

    PixelFormat GLESPixelUtil::getClosestOGREFormat(GLenum fmt)
    {
        switch (fmt)
        {
//            case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
//                return PF_PVR_RGB2;
//            case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
//                return PF_PVR_RGBA2;
//            case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
//                return PF_PVR_RGB4;
//            case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
//                return PF_PVR_RGBA4;
            case GL_LUMINANCE:
                return PF_L8;
            case GL_ALPHA:
                return PF_A8;
            case GL_LUMINANCE_ALPHA:
                return PF_BYTE_LA;
            case GL_RGB:
                return PF_X8R8G8B8;
            case GL_RGBA:
                return PF_A8R8G8B8;
#ifdef GL_BGRA
            case GL_BGRA:
#endif
//                return PF_X8B8G8R8;
            default:
                //TODO: not supported
                return PF_A8R8G8B8;
        };
    }

    size_t GLESPixelUtil::getMaxMipmaps(size_t width, size_t height, size_t depth,
                                      PixelFormat format)
    {
        size_t count = 0;

        do {
            if (width > 1)
            {
                width = width / 2;
            }
            if (height > 1)
            {
                height = height / 2;
            }
            if (depth > 1)
            {
                depth = depth / 2;
            }
            /*
            NOT needed, compressed formats will have mipmaps up to 1x1
            if(PixelUtil::isValidExtent(width, height, depth, format))
                count ++;
            else
                break;
            */
            count++;
        } while (!(width == 1 && height == 1 && depth == 1));

        return count;
    }

    size_t GLESPixelUtil::optionalPO2(size_t value)
    {
        const RenderSystemCapabilities *caps =
            Root::getSingleton().getRenderSystem()->getCapabilities();

        if (caps->hasCapability(RSC_NON_POWER_OF_2_TEXTURES))
        {
            return value;
        }
        else
        {
            return Bitwise::firstPO2From((uint32)value);
        }
    }

    PixelBox* GLESPixelUtil::convertToGLformat(const PixelBox &data,
                                             GLenum *outputFormat)
    {
        GLenum glFormat = GLESPixelUtil::getGLOriginFormat(data.format);
        if (glFormat != 0)
        {
            // format already supported
            return OGRE_NEW PixelBox(data);
        }

        PixelBox *converted = 0;

        if (data.format == PF_R8G8B8)
        {
            // Convert BGR -> RGB
            converted->format = PF_B8G8R8;
            *outputFormat = GL_RGB;

            converted = OGRE_NEW PixelBox(data);
            uint32 *data = (uint32 *) converted->data;
            for (uint i = 0; i < converted->getWidth() * converted->getHeight(); i++)
            {
                uint32 *color = data;
                *color = (*color & 0x000000ff) << 16 |
                         (*color & 0x0000FF00) |
                         (*color & 0x00FF0000) >> 16;
                data += 1;
            }
        }

        return converted;
    }
}
<|endoftext|>