<commit_before>#include "scene.hpp"

#include <iostream>

#include <Core/camera.hpp>
#include <Models/dynamicmodel.hpp>
#include <Utilities/exceptions.hpp>
#include <Utilities/log.hpp>
#include <Render/renderobject.hpp>
#include <Render/renderchain.hpp>
#include <Resources/resourcehandler.hpp>

using namespace luabridge;
using json = nlohmann::json;

// TODO Implement scene closing
// TODO Implement some sort of multithreading in lua (coroutines?)

// NOTE How slow is calling lua functions?
// NOTE What should lua be capable of doing?

Scene::Scene(const Display* const display, lua_State* luaState, std::string scenename)
        : m_display(display), m_luaState(luaState) {

    m_renderChain = std::make_unique<RenderChain>();
    m_resourceHandler = std::make_unique<ResourceHandler>();

    std::string script =  "Resources/Scenes/" + scenename + "/main.lua";
    std::string filename = "Resources/Scenes/" + scenename + "/scene.json";

    buildLuaNamespace();

    luaL_dofile(m_luaState, script.c_str());

    registerLuaFunctions();

    std::string contents;
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    if (in) {
        in.seekg(0, std::ios::end);
        contents.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&contents[0], contents.size());
        in.close();
    } else {
        throw GenericException(filename + " doesn't exist");
    }

    try {
        const json scene = json::parse(contents);
        m_resourceHandler->loadResources(scene);

        if(scene.find("staticObjects") != scene.end()) {
            std::vector<json> objects = scene["staticObjects"];
            for(const json& object : objects) {
                try {
                    std::string type = object["type"];
                    IRenderObject* rObject = nullptr;

                    // NOTE Are there other types of render obects i might want to load?
                    if(type == "line") {
                        rObject = m_resourceHandler->generateLine(object);
                    } else if(type == "staticmodel") {
                        rObject = m_resourceHandler->generateModel(object, m_resourceHandler->getResource<Model3D>(object["resource"]));
                    } else if(type == "rawstaticmodel") {
                        rObject = m_resourceHandler->generateModel(object);
                    }

                    if(rObject != nullptr) {
                        m_renderObjects.push_back(std::unique_ptr<IRenderObject>(rObject));
                    }
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }

        // TODO Implement actual dynamic model loading
        // NOTE What is "actual dynamic loading"?
        if(scene.find("dynamicObjects") != scene.end()) {
            std::vector<json> objects = scene["dynamicObjects"];
            for(const json& object : objects) {
                try {
                    auto name = object["name"];
                    //m_dynamicModels[name] = std::make_unique<DynamicModel>(m_resourceHandler->GetResource<Model3D>(object["resource"]));
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }
    } catch(std::exception& error) {
        Log::getErrorLog() << "Parsing of " << filename << " failed: " << error.what() << '\n';
    }

    for(const auto& shader : m_resourceHandler->getShaders()) {
        m_renderChain->attachShader(shader.second.get());
    }
}

// NOTE Make sure scene is 100% closed when *this* is deleted
Scene::~Scene() {
}

// NOTE What other functions are necessary to expose to lua?
void Scene::buildLuaNamespace() {
    getGlobalNamespace(m_luaState)
        .beginClass<glm::vec2>("vec2")
            .addConstructor<void(*)(float, float)>()
            .addData("x", &glm::vec2::x)
            .addData("y", &glm::vec2::y)
        .endClass()
        .beginClass<glm::vec3>("vec3")
            .addConstructor<void(*)(float, float, float)>()
            .addData("x", &glm::vec3::x)
            .addData("y", &glm::vec3::y)
            .addData("z", &glm::vec3::z)
        .endClass()
        .beginClass<glm::vec4>("vec4")
            .addConstructor<void(*)(float, float, float, float)>()
            .addData("x", &glm::vec4::x)
            .addData("y", &glm::vec4::y)
            .addData("z", &glm::vec4::z)
            .addData("w", &glm::vec4::w)
        .endClass()
        .beginNamespace("Game")
            .beginClass<Camera>("Camera")
                .addFunction("MoveCamera", &Camera::moveCamera)
                .addFunction("SetCamera", &Camera::setPosition)
                .addFunction("GetPosition", &Camera::getPosition)
                .addFunction("GetDirection", &Camera::getDirection)
            .endClass()
            .beginClass<Entity>("Entity")
                .addConstructor<void(*)(void)>()
                .addProperty("visible", &Entity::isVisible, &Entity::setVisible)
                .addProperty("name", &Entity::getName, &Entity::setName)
                .addFunction("Scale", &Entity::scale)
                .addFunction("Translate", &Entity::translate)
                .addFunction("Rotate", &Entity::rotate)
            .endClass()
            .beginClass<Scene>("Scene")
                .addFunction("SetAmbientIntensity", &Scene::setAmbientIntensity)
                .addFunction("SetAmbientColor", &Scene::setAmbientColor)
                .addFunction("BindFunctionToKey", &Scene::bindFunctionToKey)
                .addFunction("GetCamera", &Scene::getCamera)
                .addFunction("AddEntity", &Scene::addEntity)
                .addFunction("GetEntity", &Scene::getEntity)
                .addFunction("GetEntityCount", &Scene::getEntityCount)
                .addFunction("Spawn", &Scene::spawn)
            .endClass()
        .endNamespace();

    push(m_luaState, this);
    lua_setglobal(m_luaState, "Level");
}

// NOTE Are there other necessary function the engine might want to call?
void Scene::registerLuaFunctions() {
    m_startFunc = std::make_unique<LuaRef>(getGlobal(m_luaState, "Start"));
    if(!m_startFunc->isFunction()) {
        throw GenericException("Start function wasn't found");
    }

    m_renderFunc = std::make_unique<LuaRef>(getGlobal(m_luaState, "GameLoop"));
    if(!m_renderFunc->isFunction()) {
        throw GenericException("Render function wasn't found");
    }
}

// Is this the best way to do it?
void Scene::start() {
    (*m_startFunc)();
}

// NOTE Do I want to call the render func or perform a render first?
void Scene::gameLoop() {
    m_renderChain->render(m_display);
    (*m_renderFunc)();
}

// TODO Find some way to expose what keys are pressed to lua
void Scene::bindFunctionToKey(int ikey, LuaRef function, bool repeat) {
    if(!function.isFunction()) {
        throw GenericException("function wasn't found");
    }

    InputKey key = (InputKey)ikey;
    m_luaKeyBinds[key] = std::make_unique<LuaRef>(function);
    if(repeat) {
        m_display->getInputController()->registerWhileKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    } else {
        m_display->getInputController()->registerOnKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    }
}

void Scene::setAmbientIntensity(float intensity) {
    m_renderChain->setAmbientIntensity(intensity);
}

void Scene::setAmbientColor(const glm::vec3 &color) {
    m_renderChain->setAmbientColor(color);
}

// NOTE Do i want to be able to easily destroy an entity?
Entity* Scene::spawn(const std::string& name, const std::string& resource, glm::vec3 location) {
    auto res = m_resourceHandler->getResource<Model3D>(resource);
    if(res == nullptr) {
        throw BadResource("resource isn't a model or doesn't exist", resource);
    }

    if(m_entities.find(name) != m_entities.end()) {
        Log::getErrorLog() << "Attempting to spawn entity with name that has already been registered\n";
        return m_entities[name].get();
    }

    auto shader = m_resourceHandler->getShader("shader_staticmodel");
    auto dyn = new DynamicModel(res);
    dyn->translate(location);
    shader->attachRenderObject(dyn);
    m_renderObjects.push_back(std::unique_ptr<IRenderObject>(dyn));

    auto ent = new Entity();
    ent->bindModel(dyn);
    m_entities[name] = std::unique_ptr<Entity>(ent);

    return ent;
}

// NOTE What is the purpose of this?
void Scene::addEntity(const std::string& name, Entity* const ent) {
    if(m_entities.find(name) != m_entities.end()) {
        Log::error(name + " entity attempted to be added a second time, skipped");
    }

    if(ent != nullptr) {
        m_entities[name] = std::unique_ptr<Entity>(ent);
    } else {
        Log::error(name + " entity was null, skipped");
    }
}

// TODO Expand on the capabilites of an entity, ie. how does the user interact with them?
Entity* Scene::getEntity(const std::string& name) const {
    if(m_entities.find(name) != m_entities.end()) {
        return m_entities.find(name)->second.get();
    }
    return nullptr;
}

int Scene::getEntityCount() const {
    return m_entities.size();
}

Camera* Scene::getCamera() const {
    return m_display->getCamera();
}
<commit_msg>small change<commit_after>#include "scene.hpp"

#include <iostream>

#include <Core/camera.hpp>
#include <Models/dynamicmodel.hpp>
#include <Utilities/exceptions.hpp>
#include <Utilities/log.hpp>
#include <Render/renderobject.hpp>
#include <Render/renderchain.hpp>
#include <Resources/resourcehandler.hpp>

using luabridge::LuaRef;
using json = nlohmann::json;

// TODO Implement scene closing
// TODO Implement some sort of multithreading in lua (coroutines?)

// NOTE How slow is calling lua functions?
// NOTE What should lua be capable of doing?

Scene::Scene(const Display* const display, lua_State* luaState, std::string scenename)
        : m_display(display), m_luaState(luaState) {

    m_renderChain = std::make_unique<RenderChain>();
    m_resourceHandler = std::make_unique<ResourceHandler>();

    std::string script =  "Resources/Scenes/" + scenename + "/main.lua";
    std::string filename = "Resources/Scenes/" + scenename + "/scene.json";

    buildLuaNamespace();

    luaL_dofile(m_luaState, script.c_str());

    registerLuaFunctions();

    std::string contents;
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    if (in) {
        in.seekg(0, std::ios::end);
        contents.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&contents[0], contents.size());
        in.close();
    } else {
        throw GenericException(filename + " doesn't exist");
    }

    try {
        const json scene = json::parse(contents);
        m_resourceHandler->loadResources(scene);

        if(scene.find("staticObjects") != scene.end()) {
            std::vector<json> objects = scene["staticObjects"];
            for(const json& object : objects) {
                try {
                    std::string type = object["type"];
                    IRenderObject* rObject = nullptr;

                    // NOTE Are there other types of render obects i might want to load?
                    if(type == "line") {
                        rObject = m_resourceHandler->generateLine(object);
                    } else if(type == "staticmodel") {
                        rObject = m_resourceHandler->generateModel(object, m_resourceHandler->getResource<Model3D>(object["resource"]));
                    } else if(type == "rawstaticmodel") {
                        rObject = m_resourceHandler->generateModel(object);
                    }

                    if(rObject != nullptr) {
                        m_renderObjects.push_back(std::unique_ptr<IRenderObject>(rObject));
                    }
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }

        // TODO Implement actual dynamic model loading
        // NOTE What is "actual dynamic loading"?
        if(scene.find("dynamicObjects") != scene.end()) {
            std::vector<json> objects = scene["dynamicObjects"];
            for(const json& object : objects) {
                try {
                    auto name = object["name"];
                    //m_dynamicModels[name] = std::make_unique<DynamicModel>(m_resourceHandler->GetResource<Model3D>(object["resource"]));
                } catch (BadResource& error) {
                    error.printError();
                } catch (std::domain_error& error) {
                    Log::getErrorLog() << error.what() << '\n';
                }
            }
        }
    } catch(std::exception& error) {
        Log::getErrorLog() << "Parsing of " << filename << " failed: " << error.what() << '\n';
    }

    for(const auto& shader : m_resourceHandler->getShaders()) {
        m_renderChain->attachShader(shader.second.get());
    }
}

// NOTE Make sure scene is 100% closed when *this* is deleted
Scene::~Scene() {
}

// NOTE What other functions are necessary to expose to lua?
void Scene::buildLuaNamespace() {
    luabridge::getGlobalNamespace(m_luaState)
        .beginClass<glm::vec2>("vec2")
            .addConstructor<void(*)(float, float)>()
            .addData("x", &glm::vec2::x)
            .addData("y", &glm::vec2::y)
        .endClass()
        .beginClass<glm::vec3>("vec3")
            .addConstructor<void(*)(float, float, float)>()
            .addData("x", &glm::vec3::x)
            .addData("y", &glm::vec3::y)
            .addData("z", &glm::vec3::z)
        .endClass()
        .beginClass<glm::vec4>("vec4")
            .addConstructor<void(*)(float, float, float, float)>()
            .addData("x", &glm::vec4::x)
            .addData("y", &glm::vec4::y)
            .addData("z", &glm::vec4::z)
            .addData("w", &glm::vec4::w)
        .endClass()
        .beginNamespace("Game")
            .beginClass<Camera>("Camera")
                .addFunction("MoveCamera", &Camera::moveCamera)
                .addFunction("SetCamera", &Camera::setPosition)
                .addFunction("GetPosition", &Camera::getPosition)
                .addFunction("GetDirection", &Camera::getDirection)
            .endClass()
            .beginClass<Entity>("Entity")
                .addConstructor<void(*)(void)>()
                .addProperty("visible", &Entity::isVisible, &Entity::setVisible)
                .addProperty("name", &Entity::getName, &Entity::setName)
                .addFunction("Scale", &Entity::scale)
                .addFunction("Translate", &Entity::translate)
                .addFunction("Rotate", &Entity::rotate)
            .endClass()
            .beginClass<Scene>("Scene")
                .addFunction("SetAmbientIntensity", &Scene::setAmbientIntensity)
                .addFunction("SetAmbientColor", &Scene::setAmbientColor)
                .addFunction("BindFunctionToKey", &Scene::bindFunctionToKey)
                .addFunction("GetCamera", &Scene::getCamera)
                .addFunction("AddEntity", &Scene::addEntity)
                .addFunction("GetEntity", &Scene::getEntity)
                .addFunction("GetEntityCount", &Scene::getEntityCount)
                .addFunction("Spawn", &Scene::spawn)
            .endClass()
        .endNamespace();

    luabridge::setGlobal(m_luaState, this, "Level");
}

// NOTE Are there other necessary function the engine might want to call?
void Scene::registerLuaFunctions() {
    m_startFunc = std::make_unique<LuaRef>(luabridge::getGlobal(m_luaState, "Start"));
    if(!m_startFunc->isFunction()) {
        throw GenericException("Start function wasn't found");
    }

    m_renderFunc = std::make_unique<LuaRef>(luabridge::getGlobal(m_luaState, "GameLoop"));
    if(!m_renderFunc->isFunction()) {
        throw GenericException("Render function wasn't found");
    }
}

// Is this the best way to do it?
void Scene::start() {
    (*m_startFunc)();
}

// NOTE Do I want to call the render func or perform a render first?
void Scene::gameLoop() {
    m_renderChain->render(m_display);
    (*m_renderFunc)();
}

// TODO Find some way to expose what keys are pressed to lua
void Scene::bindFunctionToKey(int ikey, LuaRef function, bool repeat) {
    if(!function.isFunction()) {
        throw GenericException("function wasn't found");
    }

    InputKey key = (InputKey)ikey;
    m_luaKeyBinds[key] = std::make_unique<LuaRef>(function);
    if(repeat) {
        m_display->getInputController()->registerWhileKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    } else {
        m_display->getInputController()->registerOnKeyPressed(key, [this](InputKey key) {
            (*m_luaKeyBinds[key])();
        });
    }
}

void Scene::setAmbientIntensity(float intensity) {
    m_renderChain->setAmbientIntensity(intensity);
}

void Scene::setAmbientColor(const glm::vec3 &color) {
    m_renderChain->setAmbientColor(color);
}

// NOTE Do i want to be able to easily destroy an entity?
Entity* Scene::spawn(const std::string& name, const std::string& resource, glm::vec3 location) {
    auto res = m_resourceHandler->getResource<Model3D>(resource);
    if(res == nullptr) {
        throw BadResource("resource isn't a model or doesn't exist", resource);
    }

    if(m_entities.find(name) != m_entities.end()) {
        Log::getErrorLog() << "Attempting to spawn entity with name that has already been registered\n";
        return m_entities[name].get();
    }

    auto shader = m_resourceHandler->getShader("shader_staticmodel");
    auto dyn = new DynamicModel(res);
    dyn->translate(location);
    shader->attachRenderObject(dyn);
    m_renderObjects.push_back(std::unique_ptr<IRenderObject>(dyn));

    auto ent = new Entity();
    ent->bindModel(dyn);
    m_entities[name] = std::unique_ptr<Entity>(ent);

    return ent;
}

// NOTE What is the purpose of this?
void Scene::addEntity(const std::string& name, Entity* const ent) {
    if(m_entities.find(name) != m_entities.end()) {
        Log::error(name + " entity attempted to be added a second time, skipped");
    }

    if(ent != nullptr) {
        m_entities[name] = std::unique_ptr<Entity>(ent);
    } else {
        Log::error(name + " entity was null, skipped");
    }
}

// TODO Expand on the capabilites of an entity, ie. how does the user interact with them?
Entity* Scene::getEntity(const std::string& name) const {
    if(m_entities.find(name) != m_entities.end()) {
        return m_entities.find(name)->second.get();
    }
    return nullptr;
}

int Scene::getEntityCount() const {
    return m_entities.size();
}

Camera* Scene::getCamera() const {
    return m_display->getCamera();
}
<|endoftext|>


<commit_before>#include "SQLite.h"

#include <cstring>
#include <cassert>
#include <iostream>
#include <vector>

#include "SQLException.h"

using namespace std;
using namespace sqldb;

class SQLiteStatement : public SQLStatement {
public:
  SQLiteStatement(sqlite3 * db, sqlite3_stmt * stmt);
  ~SQLiteStatement();

  size_t execute() override;
  bool next() override;
  void reset() override;

  SQLiteStatement & bind(int value, bool is_defined) override;
  SQLiteStatement & bind(long long value, bool is_defined) override;
  SQLiteStatement & bind(double value, bool is_defined) override;
  SQLiteStatement & bind(const char * value, bool is_defined) override;
  SQLiteStatement & bind(const std::string & value, bool is_defined) override;
  SQLiteStatement & bind(const ustring & value, bool is_defined) override;
  SQLiteStatement & bind(const void* data, size_t len, bool is_defined) override;

  int getInt(int column_index, int default_value = 0) override;
  double getDouble(int column_index, double default_value = 0.0) override;
  float getFloat(int column_index, float default_value = 0.0) override;
  long long getLongLong(int column_index, long long default_value = 0) override;
  std::string getText(int column_index, std::string default_value) override;
  ustring getBlob(int column_index) override;

  bool isNull(int column_index) const override;

  int getNumFields() const override;

  long long getLastInsertId() const override;
  size_t getAffectedRows() const override;

  std::string getColumnName(int column_index) const override {
    if (column_index >= 0 && column_index < static_cast<int>(column_names_.size())) {
      return column_names_[column_index];
    } else {
      return "";
    }
  }

protected:
  void step();

private:
  sqlite3 * db_;
  sqlite3_stmt * stmt_;
  vector<const char *> column_names_;
};

SQLite::SQLite(const string & db_file, bool read_only) : db_file_(db_file), read_only_(read_only)
{
  open();
}

SQLite::SQLite(const SQLite & other) : db_file_(other.db_file_), read_only_(other.read_only_)
{
  open();
}

SQLite::SQLite(SQLite && other)
  : db_file_(std::move(other.db_file_)), db_(std::exchange(other.db_, nullptr)), read_only_(other.read_only_) { }

SQLite::~SQLite() {
  if (db_) {
    int r = sqlite3_close(db_);
    if (r) {
      cerr << "error while closing, r = " << r << endl;
    }
  }
}

static int latin1_order(unsigned char c) {
  if (c >= 'A' && c <= 'Z') return 1 + c - 'A';
  else if (c >= 'a' && c <= 'z') return 1 + c - 'a';
  else if (c == 0xc5 || c == 0xe5) return 27;
  else if (c == 0xc4 || c == 0xe4) return 28;
  else if (c == 0xd6 || c == 0xf6) return 29;
  else return c;
}

static int latin1_compare(void * arg, int len1, const void * ptr1, int len2, const void * ptr2) {
  const unsigned char * s1 = (const unsigned char *)ptr1;
  const unsigned char * s2 = (const unsigned char *)ptr2;
  for (int i = 0; i < len1 && i < len2; i++) {
    int o1 = latin1_order(s1[i]), o2 = latin1_order(s2[i]);
    if (o1 < o2) return -1;
    else if (o1 > o2) return +1;
  }
  if (len1 < len2) return -1;
  else if (len1 > len2) return +1;
  else return 0;
}

bool
SQLite::open() {
  int flags = 0;
  if (db_file_.empty()) {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  } else if (read_only_) {
    flags = SQLITE_OPEN_READONLY;
  } else {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  }
  int r = sqlite3_open_v2(db_file_.c_str(), &db_, flags, 0);
  if (r) {
    db_ = 0;
    throw SQLException(SQLException::OPEN_FAILED, sqlite3_errmsg(db_));
  }

  if (db_) {
    sqlite3_busy_timeout(db_, 1000);

    r = sqlite3_create_collation( db_,
				  "NOCASE", // "latin1",
				  SQLITE_UTF8,
				  0, // this,
				  latin1_compare
				  );
    if (r) {
      cerr << "failed to create NOCASE collation\n";
    }
  }

  return true;
}

std::unique_ptr<sqldb::SQLStatement>
SQLite::prepare(const string & query) {
  if (!db_) {
    throw SQLException(SQLException::PREPARE_FAILED);
  }
  sqlite3_stmt * stmt = 0;
  int r = sqlite3_prepare_v2(db_, query.c_str(), -1, &stmt, 0);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::PREPARE_FAILED, sqlite3_errmsg(db_));
  }
  assert(stmt);
  return std::make_unique<SQLiteStatement>(db_, stmt);
}

SQLiteStatement::SQLiteStatement(sqlite3 * db, sqlite3_stmt * stmt) : db_(db), stmt_(stmt) {
  assert(db_);
  assert(stmt_);

  for (int i = 0, n = getNumFields(); i < n; i++) {
    column_names_.push_back(sqlite3_column_name(stmt_, i));
  }
}

SQLiteStatement::~SQLiteStatement() {
  if (stmt_) sqlite3_finalize(stmt_);
}

size_t
SQLiteStatement::execute() {
  step();
  return getAffectedRows();
}

void
SQLiteStatement::step() {
  results_available = false;

  while ( 1 ) {
    int r = sqlite3_step(stmt_);
    switch (r) {
    case SQLITE_ROW:
      results_available = true;
      return;

    case SQLITE_DONE:
      return;

    case SQLITE_BUSY:
      cerr << "database is busy\n";
      break;

    case SQLITE_ERROR: throw SQLException(SQLException::DATABASE_ERROR, sqlite3_errmsg(db_));
    case SQLITE_MISUSE: throw SQLException(SQLException::DATABASE_MISUSE, sqlite3_errmsg(db_));
    case SQLITE_CONSTRAINT: throw SQLException(SQLException::CONSTRAINT_VIOLATION, sqlite3_errmsg(db_));

    default:
      cerr << "unknown error: " << r << endl;
      assert(0);
      return;
    }
  }

  throw SQLException(SQLException::QUERY_TIMED_OUT);
}

void
SQLiteStatement::reset() {
  SQLStatement::reset();

  int r = sqlite3_reset(stmt_);

  switch (r) {
  case SQLITE_OK: return;

  case SQLITE_SCHEMA:
    throw SQLException(SQLException::SCHEMA_CHANGED, sqlite3_errmsg(db_));
    return;

  default:
    cerr << "unknown error: " << r << endl;
    assert(0);
    return;
  }
}

bool
SQLiteStatement::next() {
  step();
  return results_available;
}

SQLiteStatement &
SQLiteStatement::bind(int value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  if (is_defined) {
    int r = sqlite3_bind_int(stmt_, index, value);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(long long value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  if (is_defined) {
    int r = sqlite3_bind_int64(stmt_, index, (sqlite_int64)value);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(double value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  if (is_defined) {
    int r = sqlite3_bind_double(stmt_, index, value);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const char * value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  if (is_defined) {
    assert(value);
    int r = sqlite3_bind_text(stmt_, index, value, (int)strlen(value), SQLITE_TRANSIENT);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const std::string & value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  if (is_defined) {
    int r = sqlite3_bind_text(stmt_, index, value.c_str(), (int)value.size(), SQLITE_TRANSIENT);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const ustring & value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  if (is_defined) {
    int r = sqlite3_bind_blob(stmt_, index, value.data(), value.size(), SQLITE_TRANSIENT);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const void* data, size_t len, bool is_defined = true) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  if (is_defined) {
    int r = sqlite3_bind_blob(stmt_, index, data, len, SQLITE_TRANSIENT);
    if (r != SQLITE_OK) {
      throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
    }
  }
  return *this;
}

int
SQLiteStatement::getInt(int column_index, int default_value) {
  if (!isNull(column_index)) {
    return sqlite3_column_int(stmt_, column_index);
  }
  return default_value;
}

double
SQLiteStatement::getDouble(int column_index, double default_value) {
  if (!isNull(column_index)) {
    return sqlite3_column_double(stmt_, column_index);
  }
  return default_value;
}

float
SQLiteStatement::getFloat(int column_index, float default_value) {
  if (!isNull(column_index)) {
    return static_cast<float>(sqlite3_column_double(stmt_, column_index));
  }
  return default_value;
}

long long
SQLiteStatement::getLongLong(int column_index, long long default_value) {
  if (!isNull(column_index)) {
    return sqlite3_column_int64(stmt_, column_index);
  }
  return default_value;
}

std::string
SQLiteStatement::getText(int column_index, std::string default_value) {
  if (!isNull(column_index)) {
    const char * s = (const char *)sqlite3_column_text(stmt_, column_index);
    if (s) {
      return string(s);
    }
  }
  return move(default_value);
}

ustring
SQLiteStatement::getBlob(int column_index) {
  if (!isNull(column_index)) {
    auto data = sqlite3_column_blob(stmt_, column_index);
    auto len = sqlite3_column_bytes(stmt_, column_index);
    return ustring((const unsigned char *)data, len);
  } else {
    return ustring();
  }
}

bool
SQLiteStatement::isNull(int column_index) const {
  if (!results_available) {
    return true;
  } else {
    return stmt_ ? sqlite3_column_type(stmt_, column_index) == SQLITE_NULL : true;
  }
}

int
SQLiteStatement::getNumFields() const {
  return stmt_ ? sqlite3_column_count(stmt_) : 0;
}

long long
SQLiteStatement::getLastInsertId() const {
  return sqlite3_last_insert_rowid(db_);
}

size_t
SQLiteStatement::getAffectedRows() const {
  return sqlite3_changes(db_);
}
<commit_msg>bind nulls<commit_after>#include "SQLite.h"

#include <cstring>
#include <cassert>
#include <iostream>
#include <vector>

#include "SQLException.h"

using namespace std;
using namespace sqldb;

class SQLiteStatement : public SQLStatement {
public:
  SQLiteStatement(sqlite3 * db, sqlite3_stmt * stmt);
  ~SQLiteStatement();

  size_t execute() override;
  bool next() override;
  void reset() override;

  SQLiteStatement & bind(int value, bool is_defined) override;
  SQLiteStatement & bind(long long value, bool is_defined) override;
  SQLiteStatement & bind(double value, bool is_defined) override;
  SQLiteStatement & bind(const char * value, bool is_defined) override;
  SQLiteStatement & bind(const std::string & value, bool is_defined) override;
  SQLiteStatement & bind(const ustring & value, bool is_defined) override;
  SQLiteStatement & bind(const void* data, size_t len, bool is_defined) override;

  int getInt(int column_index, int default_value = 0) override;
  double getDouble(int column_index, double default_value = 0.0) override;
  float getFloat(int column_index, float default_value = 0.0) override;
  long long getLongLong(int column_index, long long default_value = 0) override;
  std::string getText(int column_index, std::string default_value) override;
  ustring getBlob(int column_index) override;

  bool isNull(int column_index) const override;

  int getNumFields() const override;

  long long getLastInsertId() const override;
  size_t getAffectedRows() const override;

  std::string getColumnName(int column_index) const override {
    if (column_index >= 0 && column_index < static_cast<int>(column_names_.size())) {
      return column_names_[column_index];
    } else {
      return "";
    }
  }

protected:
  void step();

private:
  sqlite3 * db_;
  sqlite3_stmt * stmt_;
  vector<const char *> column_names_;
};

SQLite::SQLite(const string & db_file, bool read_only) : db_file_(db_file), read_only_(read_only)
{
  open();
}

SQLite::SQLite(const SQLite & other) : db_file_(other.db_file_), read_only_(other.read_only_)
{
  open();
}

SQLite::SQLite(SQLite && other)
  : db_file_(std::move(other.db_file_)), db_(std::exchange(other.db_, nullptr)), read_only_(other.read_only_) { }

SQLite::~SQLite() {
  if (db_) {
    int r = sqlite3_close(db_);
    if (r) {
      cerr << "error while closing, r = " << r << endl;
    }
  }
}

static int latin1_order(unsigned char c) {
  if (c >= 'A' && c <= 'Z') return 1 + c - 'A';
  else if (c >= 'a' && c <= 'z') return 1 + c - 'a';
  else if (c == 0xc5 || c == 0xe5) return 27;
  else if (c == 0xc4 || c == 0xe4) return 28;
  else if (c == 0xd6 || c == 0xf6) return 29;
  else return c;
}

static int latin1_compare(void * arg, int len1, const void * ptr1, int len2, const void * ptr2) {
  const unsigned char * s1 = (const unsigned char *)ptr1;
  const unsigned char * s2 = (const unsigned char *)ptr2;
  for (int i = 0; i < len1 && i < len2; i++) {
    int o1 = latin1_order(s1[i]), o2 = latin1_order(s2[i]);
    if (o1 < o2) return -1;
    else if (o1 > o2) return +1;
  }
  if (len1 < len2) return -1;
  else if (len1 > len2) return +1;
  else return 0;
}

bool
SQLite::open() {
  int flags = 0;
  if (db_file_.empty()) {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  } else if (read_only_) {
    flags = SQLITE_OPEN_READONLY;
  } else {
    flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
  }
  int r = sqlite3_open_v2(db_file_.c_str(), &db_, flags, 0);
  if (r) {
    db_ = 0;
    throw SQLException(SQLException::OPEN_FAILED, sqlite3_errmsg(db_));
  }

  if (db_) {
    sqlite3_busy_timeout(db_, 1000);

    r = sqlite3_create_collation( db_,
				  "NOCASE", // "latin1",
				  SQLITE_UTF8,
				  0, // this,
				  latin1_compare
				  );
    if (r) {
      cerr << "failed to create NOCASE collation\n";
    }
  }

  return true;
}

std::unique_ptr<sqldb::SQLStatement>
SQLite::prepare(const string & query) {
  if (!db_) {
    throw SQLException(SQLException::PREPARE_FAILED);
  }
  sqlite3_stmt * stmt = 0;
  int r = sqlite3_prepare_v2(db_, query.c_str(), -1, &stmt, 0);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::PREPARE_FAILED, sqlite3_errmsg(db_));
  }
  assert(stmt);
  return std::make_unique<SQLiteStatement>(db_, stmt);
}

SQLiteStatement::SQLiteStatement(sqlite3 * db, sqlite3_stmt * stmt) : db_(db), stmt_(stmt) {
  assert(db_);
  assert(stmt_);

  for (int i = 0, n = getNumFields(); i < n; i++) {
    column_names_.push_back(sqlite3_column_name(stmt_, i));
  }
}

SQLiteStatement::~SQLiteStatement() {
  if (stmt_) sqlite3_finalize(stmt_);
}

size_t
SQLiteStatement::execute() {
  step();
  return getAffectedRows();
}

void
SQLiteStatement::step() {
  results_available = false;

  while ( 1 ) {
    int r = sqlite3_step(stmt_);
    switch (r) {
    case SQLITE_ROW:
      results_available = true;
      return;

    case SQLITE_DONE:
      return;

    case SQLITE_BUSY:
      cerr << "database is busy\n";
      break;

    case SQLITE_ERROR: throw SQLException(SQLException::DATABASE_ERROR, sqlite3_errmsg(db_));
    case SQLITE_MISUSE: throw SQLException(SQLException::DATABASE_MISUSE, sqlite3_errmsg(db_));
    case SQLITE_CONSTRAINT: throw SQLException(SQLException::CONSTRAINT_VIOLATION, sqlite3_errmsg(db_));

    default:
      cerr << "unknown error: " << r << endl;
      assert(0);
      return;
    }
  }

  throw SQLException(SQLException::QUERY_TIMED_OUT);
}

void
SQLiteStatement::reset() {
  SQLStatement::reset();

  int r = sqlite3_reset(stmt_);

  switch (r) {
  case SQLITE_OK: return;

  case SQLITE_SCHEMA:
    throw SQLException(SQLException::SCHEMA_CHANGED, sqlite3_errmsg(db_));
    return;

  default:
    cerr << "unknown error: " << r << endl;
    assert(0);
    return;
  }
}

bool
SQLiteStatement::next() {
  step();
  return results_available;
}

SQLiteStatement &
SQLiteStatement::bind(int value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  int r;
  if (is_defined) r = sqlite3_bind_int(stmt_, index, value);
  else r = sqlite3_bind_null(stmt_, index);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(long long value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  int r;
  if (is_defined) r = sqlite3_bind_int64(stmt_, index, (sqlite_int64)value);
  else r = sqlite3_bind_null(stmt_, index);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(double value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  int r;
  if (is_defined) r = sqlite3_bind_double(stmt_, index, value);
  else r = sqlite3_bind_null(stmt_, index);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const char * value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  int r;
  if (is_defined) r = sqlite3_bind_text(stmt_, index, value, (int)strlen(value), SQLITE_TRANSIENT);
  else r = sqlite3_bind_null(stmt_, index);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const std::string & value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  int r;
  if (is_defined) r = sqlite3_bind_text(stmt_, index, value.c_str(), (int)value.size(), SQLITE_TRANSIENT);
  else r = sqlite3_bind_null(stmt_, index);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const ustring & value, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  int r;
  if (is_defined) r = sqlite3_bind_blob(stmt_, index, value.data(), value.size(), SQLITE_TRANSIENT);
  else r = sqlite3_bind_null(stmt_, index);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
  }
  return *this;
}

SQLiteStatement &
SQLiteStatement::bind(const void* data, size_t len, bool is_defined) {
  assert(stmt_);
  unsigned int index = getNextBindIndex();
  int r;
  if (is_defined) r = sqlite3_bind_blob(stmt_, index, data, len, SQLITE_TRANSIENT);
  else r = sqlite3_bind_null(stmt_, index);
  if (r != SQLITE_OK) {
    throw SQLException(SQLException::BIND_FAILED, sqlite3_errmsg(db_));
  }
  return *this;
}

int
SQLiteStatement::getInt(int column_index, int default_value) {
  if (!isNull(column_index)) {
    return sqlite3_column_int(stmt_, column_index);
  }
  return default_value;
}

double
SQLiteStatement::getDouble(int column_index, double default_value) {
  if (!isNull(column_index)) {
    return sqlite3_column_double(stmt_, column_index);
  }
  return default_value;
}

float
SQLiteStatement::getFloat(int column_index, float default_value) {
  if (!isNull(column_index)) {
    return static_cast<float>(sqlite3_column_double(stmt_, column_index));
  }
  return default_value;
}

long long
SQLiteStatement::getLongLong(int column_index, long long default_value) {
  if (!isNull(column_index)) {
    return sqlite3_column_int64(stmt_, column_index);
  }
  return default_value;
}

std::string
SQLiteStatement::getText(int column_index, std::string default_value) {
  if (!isNull(column_index)) {
    const char * s = (const char *)sqlite3_column_text(stmt_, column_index);
    if (s) {
      return string(s);
    }
  }
  return move(default_value);
}

ustring
SQLiteStatement::getBlob(int column_index) {
  if (!isNull(column_index)) {
    auto data = sqlite3_column_blob(stmt_, column_index);
    auto len = sqlite3_column_bytes(stmt_, column_index);
    return ustring((const unsigned char *)data, len);
  } else {
    return ustring();
  }
}

bool
SQLiteStatement::isNull(int column_index) const {
  if (!results_available) {
    return true;
  } else {
    return stmt_ ? sqlite3_column_type(stmt_, column_index) == SQLITE_NULL : true;
  }
}

int
SQLiteStatement::getNumFields() const {
  return stmt_ ? sqlite3_column_count(stmt_) : 0;
}

long long
SQLiteStatement::getLastInsertId() const {
  return sqlite3_last_insert_rowid(db_);
}

size_t
SQLiteStatement::getAffectedRows() const {
  return sqlite3_changes(db_);
}
<|endoftext|>


<commit_before><commit_msg>Started implementation of quartiles<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// WriteBatch::rep_ :=
//    sequence: fixed64
//    count: fixed32
//    data: record[count]
// record :=
//    kTypeValue varstring varstring         |
//    kTypeDeletion varstring
// varstring :=
//    len: varint32
//    data: uint8[len]

#include "leveldb/write_batch.h"

#include "leveldb/db.h"
#include "db/dbformat.h"
#include "db/memtable.h"
#include "db/write_batch_internal.h"
#include "util/coding.h"

namespace leveldb {

// WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
static const size_t kHeader = 12;

WriteBatch::WriteBatch() {
  Clear();
}

WriteBatch::~WriteBatch() { }

WriteBatch::Handler::~Handler() { }

void WriteBatch::Clear() {
  rep_.clear();
  rep_.resize(kHeader);
}

Status WriteBatch::Iterate(Handler* handler) const {
  Slice input(rep_);
  if (input.size() < kHeader) {
    return Status::Corruption("malformed WriteBatch (too small)");
  }

  input.remove_prefix(kHeader);
  Slice key, value;
  int found = 0;
  while (!input.empty()) {
    found++;
    char tag = input[0];
    input.remove_prefix(1);
    switch (tag) {
      case kTypeValue:
        if (GetLengthPrefixedSlice(&input, &key) &&
            GetLengthPrefixedSlice(&input, &value)) {
          handler->Put(key, value);
        } else {
          return Status::Corruption("bad WriteBatch Put");
        }
        break;
      case kTypeDeletion:
        if (GetLengthPrefixedSlice(&input, &key)) {
          handler->Delete(key);
        } else {
          return Status::Corruption("bad WriteBatch Delete");
        }
        break;
      default:
        return Status::Corruption("unknown WriteBatch tag");
    }
  }
  if (found != WriteBatchInternal::Count(this)) {
    return Status::Corruption("WriteBatch has wrong count");
  } else {
    return Status::OK();
  }
}

int WriteBatchInternal::Count(const WriteBatch* b) {
  return DecodeFixed32(b->rep_.data() + 8);
}

void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
  EncodeFixed32(&b->rep_[8], n);
}

SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
  return SequenceNumber(DecodeFixed64(b->rep_.data()));
}

void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
  EncodeFixed64(&b->rep_[0], seq);
}

void WriteBatch::Put(const Slice& key, const Slice& value) {
  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  rep_.push_back(static_cast<char>(kTypeValue));
  PutLengthPrefixedSlice(&rep_, key);
  PutLengthPrefixedSlice(&rep_, value);
}

void WriteBatch::Delete(const Slice& key) {
  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  rep_.push_back(static_cast<char>(kTypeDeletion));
  PutLengthPrefixedSlice(&rep_, key);
}

namespace {
class MemTableInserter : public WriteBatch::Handler {
 public:
  SequenceNumber sequence_;
  MemTable* mem_;

  virtual void Put(const Slice& key, const Slice& value) {
    mem_->Add(sequence_, kTypeValue, key, value);
    sequence_++;
  }
  virtual void Delete(const Slice& key) {
    mem_->Add(sequence_, kTypeDeletion, key, Slice());
    sequence_++;
  }
};
}  // namespace

Status WriteBatchInternal::InsertInto(const WriteBatch* b,
                                      MemTable* memtable) {
  MemTableInserter inserter;
  inserter.sequence_ = WriteBatchInternal::Sequence(b);
  inserter.mem_ = memtable;
  return b->Iterate(&inserter);
}

void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
  assert(contents.size() >= kHeader);
  b->rep_.assign(contents.data(), contents.size());
}

void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) {
  SetCount(dst, Count(dst) + Count(src));
  assert(src->rep_.size() >= kHeader);
  dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
}

}  // namespace leveldb
<commit_msg>Put in stub logic for expiry items within a write batch.<commit_after>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// WriteBatch::rep_ :=
//    sequence: fixed64
//    count: fixed32
//    data: record[count]
// record :=
//    kTypeValue varstring varstring         |
//    kTypeDeletion varstring
// varstring :=
//    len: varint32
//    data: uint8[len]

#include "leveldb/write_batch.h"

#include "leveldb/db.h"
#include "db/dbformat.h"
#include "db/memtable.h"
#include "db/write_batch_internal.h"
#include "util/coding.h"

namespace leveldb {

// WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
static const size_t kHeader = 12;

WriteBatch::WriteBatch() {
  Clear();
}

WriteBatch::~WriteBatch() { }

WriteBatch::Handler::~Handler() { }

void WriteBatch::Clear() {
  rep_.clear();
  rep_.resize(kHeader);
}

Status WriteBatch::Iterate(Handler* handler) const {
  Slice input(rep_);
  if (input.size() < kHeader) {
    return Status::Corruption("malformed WriteBatch (too small)");
  }

  input.remove_prefix(kHeader);
  Slice key, value;
  ExpiryTime expiry;
  int found = 0;
  while (!input.empty()) {
    found++;
    char tag = input[0];
    input.remove_prefix(1);
    switch (tag) {
      case kTypeValue:
        if (GetLengthPrefixedSlice(&input, &key) &&
            GetLengthPrefixedSlice(&input, &value)) {
          handler->Put(key, value);
        } else {
          return Status::Corruption("bad WriteBatch Put");
        }
        break;
      case kTypeDeletion:
        if (GetLengthPrefixedSlice(&input, &key)) {
          handler->Delete(key);
        } else {
          return Status::Corruption("bad WriteBatch Delete");
        }
        break;
      case kTypeValueWriteTime:
      case kTypeValueExplicitExpiry:
        if (GetLengthPrefixedSlice(&input, &key) &&
            GetVarint64(&input, &expiry) &&
            GetLengthPrefixedSlice(&input, &value)) {
          handler->Put(key, value);
        } else {
          return Status::Corruption("bad WriteBatch Expiry");
        }
        break;
      default:
        return Status::Corruption("unknown WriteBatch tag");
    }
  }
  if (found != WriteBatchInternal::Count(this)) {
    return Status::Corruption("WriteBatch has wrong count");
  } else {
    return Status::OK();
  }
}

int WriteBatchInternal::Count(const WriteBatch* b) {
  return DecodeFixed32(b->rep_.data() + 8);
}

void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
  EncodeFixed32(&b->rep_[8], n);
}

SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
  return SequenceNumber(DecodeFixed64(b->rep_.data()));
}

void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
  EncodeFixed64(&b->rep_[0], seq);
}

void WriteBatch::Put(const Slice& key, const Slice& value) {
  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  rep_.push_back(static_cast<char>(kTypeValue));
  PutLengthPrefixedSlice(&rep_, key);
  PutLengthPrefixedSlice(&rep_, value);
}

void WriteBatch::Delete(const Slice& key) {
  WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  rep_.push_back(static_cast<char>(kTypeDeletion));
  PutLengthPrefixedSlice(&rep_, key);
}

namespace {
class MemTableInserter : public WriteBatch::Handler {
 public:
  SequenceNumber sequence_;
  MemTable* mem_;

  virtual void Put(const Slice& key, const Slice& value) {
    mem_->Add(sequence_, kTypeValue, key, value);
    sequence_++;
  }
  virtual void Delete(const Slice& key) {
    mem_->Add(sequence_, kTypeDeletion, key, Slice());
    sequence_++;
  }
};
}  // namespace

Status WriteBatchInternal::InsertInto(const WriteBatch* b,
                                      MemTable* memtable) {
  MemTableInserter inserter;
  inserter.sequence_ = WriteBatchInternal::Sequence(b);
  inserter.mem_ = memtable;
  return b->Iterate(&inserter);
}

void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
  assert(contents.size() >= kHeader);
  b->rep_.assign(contents.data(), contents.size());
}

void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) {
  SetCount(dst, Count(dst) + Count(src));
  assert(src->rep_.size() >= kHeader);
  dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
}

}  // namespace leveldb
<|endoftext|>


<commit_before>//
// SettingsMVC.cpp
// MultitouchPadOsc is released under the MIT License.
//
// Copyright (c) 2011 - 2012, Paul Vollmer http://www.wrong-entertainment.com
//
// 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 "SettingsMVC.h"

SettingsMVC::SettingsMVC(){}

void SettingsMVC::init(ofTrueTypeFont font) {
	cout << "ViewerSettings init()";

	checkboxOscArray.init(font, "osc array xysa", 15, 170);
	checkboxFrame.init(font, "frame active", 15, 190);
	//checkboxTimestamp.init(vera, "timestamp active",  60, 170, defXmlPadTimestamp);
	checkboxPosition.init(font, "x-, y-position active", 15, 210);
	//checkboxVelocity.init(vera, "x-, y-velocity active", 60, 200, defXmlPadVelocity);
	//checkboxMaxis.init(vera, "minor-, major-axis active", 60, 215, defXmlPadMaxis);
	checkboxSize.init(font, "size active", 15, 230);
	checkboxAngle.init(font, "angle active", 15, 250);
}

void SettingsMVC::getXml(ofxXmlDefaultSettings xml) {
	/* OSC variables
	 */
	oscHost = xml.getAttribute("osc", "host", "127.0.0.1", 0);
	oscPort = xml.getAttribute("osc", "port", 12345, 0);

	/* Trackpad variables
	 */
	oscTouchpadDevicename = xml.getValue("pad:devicename", "mtpadosc");
	checkboxOscArray.status  = xml.getValue("pad:array", false, 0);
	//oscArrayActive = xml.getValue("pad:array", false, 0);
	checkboxFrame.status = xml.getValue("pad:frame", false, 0);
	//checkboxTimestamp.status = xml.getValue("pad:timestamp", false, 0);
	checkboxPosition.status = xml.getValue("pad:position", false, 0);
	//checkboxVelocity.status = xml.getValue("pad:velocity", false, 0);
	checkboxSize.status = xml.getValue("pad:size", false, 0);
	//checkboxMaxis.status = xml.getValue("pad:maxis", false, 0);
	checkboxAngle.status = xml.getValue("pad:angle", false, 0);
}

void SettingsMVC::addXml(ofxXmlDefaultSettings xml) {
	/* OSC variables
	 */
	oscHost = "127.0.0.1";
	oscPort = 12345;
	xml.addAttribute("osc", "host", oscHost, 0);
	xml.addAttribute("osc", "post", oscPort, 0);

	/* Trackpad variables
	 */
	oscTouchpadDevicename = "mtpad";

 	checkboxOscArray.status = false;
	checkboxFrame.status = false;
	//checkboxTimestamp.status = false;
	checkboxPosition.status = false;
	//checkboxVelocity.status = false;
	checkboxSize.status = false;
	//checkboxMaxis.status = false;
	checkboxAngle.status = false;
	xml.addTag("pad");
	xml.pushTag("pad", 0);
	xml.addValue("devicename", oscTouchpadDevicename);
	xml.addValue("array", checkboxOscArray.status);
	xml.addValue("frame", checkboxFrame.status);
	//xml.addValue("timestamp", checkboxTimestamp.status);
	xml.addValue("position", checkboxPosition.status);
	//xml.addValue("velocity", checkboxVelocity.status);
	xml.addValue("size", checkboxSize.status);
	//xml.addValue("maxis", checkboxMaxis.status);
	xml.addValue("angle", checkboxAngle.status);
	xml.popTag();
}

void SettingsMVC::setXml(ofxXmlDefaultSettings xml) {
	xml.pushRoot();

	xml.setAttribute("osc", "host", oscHost, 0);
	xml.setAttribute("osc", "port", oscPort, 0);

	xml.setValue("pad:devicename", oscTouchpadDevicename, 0);
	xml.setValue("pad:array", checkboxOscArray.status, 0);
	xml.setValue("pad:frame", checkboxFrame.status, 0);
	//xml.setValue("pad:timestamp", checkboxTimestamp.status, 0);
	xml.setValue("pad:position", checkboxPosition.status, 0);
	//xml.setValue("pad:velocity", checkboxVelocity.status, 0);
	xml.setValue("pad:size", checkboxSize.status, 0);
	//xml.setValue("pad:maxis", checkboxMaxis.status, 0);
	xml.setValue("pad:angle", checkboxAngle.status, 0);

	xml.popRoot();
}

void SettingsMVC::log(){
	ofLog() << "XML: osc:host        = " << oscHost;
	ofLog() << "XML: osc:port        = " << oscPort;

	ofLog() << "pad:devicename  = " << oscTouchpadDevicename;
	ofLog() << "pad:array       = " << checkboxOscArray.status;
	ofLog() << "pad:frame       = " << checkboxFrame.status;
	//ofLog() << "pad:timestamp   = " << checkboxTimestamp.status;
	ofLog() << "pad:position    = " << checkboxPosition.status;
	//ofLog() << "pad:velocity    = " << checkboxVelocity.status;
	ofLog() << "pad:size        = " << checkboxSize.status;
	//ofLog() << "pad:maxis       = " << checkboxMaxis.status;
	ofLog() << "pad:angle       = " << checkboxAngle.status;
}

void SettingsMVC::draw(ofTrueTypeFont font) {
	// ground
	ofEnableAlphaBlending();
	ofSetColor(0, 150);
	ofFill();
	ofRect(10, 30, ofGetWidth()-20, ofGetHeight()-40);
	ofDisableAlphaBlending();
	// Osc settings
	ofSetColor(ofColor::white);
	ofFill();
	font.drawString("OSC SETTINGS", 15, 50);
	// Host: xxx.xxx.xxx.xxx Port: xxxx, Touch Count
	font.drawString("Host: ", 15, 90);
	font.drawString("Port: ", 15, 110);
	font.drawString("Devicename: ", 15, 130);
	font.drawString("[To open the settings xml, press key 's']", 167, 150);

	checkboxOscArray.display();
	checkboxFrame.display();
	//cbTimestamp.display();
	checkboxPosition.display();
	//cbVelocity.display();
	//cbMaxis.display();
	checkboxSize.display();
	checkboxAngle.display();
	// shortcuts
	font.drawString("[Shortcut: 2]", 350, 200);
	font.drawString("[Shortcut: 3]", 350, 220);
	font.drawString("[Shortcut: 4]", 350, 240);
	font.drawString("[Shortcut: 5]", 350, 260);

	// TODO:
	//vera.drawString(ofToString("Number of Devices: ") + ofToString(pad.getNumDevices()), 15, 150);
}

void SettingsMVC::mousePressed(int x, int y) {
	cout << "ViewerSettings mousePressed()";
	/* Check boxes
	 */
	checkboxOscArray.pressed(x, y);
	checkboxFrame.pressed(x, y);
	//cbTimestamp.pressed(x, y);
	checkboxPosition.pressed(x, y);
	//cbVelocity.pressed(x, y);
	//cbMaxis.pressed(x, y);
	checkboxSize.pressed(x, y);
	checkboxAngle.pressed(x, y);
}

void SettingsMVC::keyPressed(int key) {
	switch (key) {
		/* OSC frame
		 */
		case 'w':
			if (checkboxFrame.status == true) {
				checkboxFrame.status = false;
			} else {
				checkboxFrame.status = true;
			}
			//console.addString("Shortcut padFrame: " + ofToString(xmlPadFrame), true);
			break;

			/* OSC timestamp
			 */
			/*case '3':
			 if (settings.padTimestamp == 0) {
			 settings.padTimestamp = 1;
			 } else {
			 settings.padTimestamp = 0;
			 }
			 cbTimestamp.status = settings.padTimestamp;

			 cout << "Shortcut padTimestamp: " << settings.padTimestamp << endl;
			 break;*/

		/* OSC position
		 */
		case 'e':
			if (checkboxPosition.status == true) {
				checkboxPosition.status = false;
			} else {
				checkboxPosition.status = true;
			}
			//console.addString("Shortcut padPosition: " + ofToString(xmlPadPosition), true);
			break;

			/* OSC velocity
			 */
			/*case '5':
			 if (settings.padVelocity == 0) {
			 settings.padVelocity = 1;
			 } else {
			 settings.padVelocity = 0;
			 }
			 cbVelocity.status = settings.padVelocity;

			 cout << "Shortcut padVelocity: " << settings.padVelocity << endl;
			 break;*/

			/* OSC maxis
			 */
			/*case '4':
			 if (settings.padMaxis == 0) {
			 settings.padMaxis = 1;
			 } else {
			 settings.padMaxis = 0;
			 }
			 cbMaxis.status = settings.padMaxis;

			 cout << "Shortcut padMaxis: " << settings.padMaxis << endl;
			 break;*/

		/* OSC maxis
		 */
		case 'r':
			if (checkboxSize.status == true) {
				checkboxSize.status = false;
			} else {
				checkboxSize.status = true;
			}
			//console.addString("Shortcut padSize: " + ofToString(xmlPadSize), true);
			break;

		/* OSC angle
		 */
		case 't':
			if (checkboxAngle.status == true) {
				checkboxAngle.status = false;
			} else {
				checkboxAngle.status = true;
			}
			//console.addString("Shortcut padAngle: " + ofToString(xmlPadAngle), true);
			break;

		default:
			break;
	}
}
<commit_msg>small changes at default status settings<commit_after>//
// SettingsMVC.cpp
// MultitouchPadOsc is released under the MIT License.
//
// Copyright (c) 2011 - 2012, Paul Vollmer http://www.wrong-entertainment.com
//
// 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 "SettingsMVC.h"

SettingsMVC::SettingsMVC(){}

void SettingsMVC::init(ofTrueTypeFont font) {
	cout << "ViewerSettings init()";

	checkboxOscArray.init(font, "osc array xysa", 15, 170);
	checkboxFrame.init(font, "frame active", 15, 190);
	//checkboxTimestamp.init(vera, "timestamp active",  60, 170, defXmlPadTimestamp);
	checkboxPosition.init(font, "x-, y-position active", 15, 210);
	//checkboxVelocity.init(vera, "x-, y-velocity active", 60, 200, defXmlPadVelocity);
	//checkboxMaxis.init(vera, "minor-, major-axis active", 60, 215, defXmlPadMaxis);
	checkboxSize.init(font, "size active", 15, 230);
	checkboxAngle.init(font, "angle active", 15, 250);
}

void SettingsMVC::getXml(ofxXmlDefaultSettings xml) {
	/* OSC variables
	 */
	oscHost = xml.getAttribute("osc", "host", "127.0.0.1", 0);
	oscPort = xml.getAttribute("osc", "port", 12345, 0);

	/* Trackpad variables
	 */
	oscTouchpadDevicename = xml.getValue("pad:devicename", "mtpadosc");
	checkboxOscArray.status  = xml.getValue("pad:array", false, 0);
	//oscArrayActive = xml.getValue("pad:array", false, 0);
	checkboxFrame.status = xml.getValue("pad:frame", false, 0);
	//checkboxTimestamp.status = xml.getValue("pad:timestamp", false, 0);
	checkboxPosition.status = xml.getValue("pad:position", false, 0);
	//checkboxVelocity.status = xml.getValue("pad:velocity", false, 0);
	checkboxSize.status = xml.getValue("pad:size", false, 0);
	//checkboxMaxis.status = xml.getValue("pad:maxis", false, 0);
	checkboxAngle.status = xml.getValue("pad:angle", false, 0);
}

void SettingsMVC::addXml(ofxXmlDefaultSettings xml) {
	/* OSC variables
	 */
	oscHost = "127.0.0.1";
	oscPort = 12345;
	xml.addAttribute("osc", "host", oscHost, 0);
	xml.addAttribute("osc", "post", oscPort, 0);

	/* Trackpad variables
	 */
	oscTouchpadDevicename = "mtpad";

 	checkboxOscArray.status = false;
	checkboxFrame.status = false;
	//checkboxTimestamp.status = false;
	checkboxPosition.status = true;
	//checkboxVelocity.status = false;
	checkboxSize.status = true;
	//checkboxMaxis.status = false;
	checkboxAngle.status = true;
	xml.addTag("pad");
	xml.pushTag("pad", 0);
	xml.addValue("devicename", oscTouchpadDevicename);
	xml.addValue("array", checkboxOscArray.status);
	xml.addValue("frame", checkboxFrame.status);
	//xml.addValue("timestamp", checkboxTimestamp.status);
	xml.addValue("position", checkboxPosition.status);
	//xml.addValue("velocity", checkboxVelocity.status);
	xml.addValue("size", checkboxSize.status);
	//xml.addValue("maxis", checkboxMaxis.status);
	xml.addValue("angle", checkboxAngle.status);
	xml.popTag();
}

void SettingsMVC::setXml(ofxXmlDefaultSettings xml) {
	xml.pushRoot();

	xml.setAttribute("osc", "host", oscHost, 0);
	xml.setAttribute("osc", "port", oscPort, 0);

	xml.setValue("pad:devicename", oscTouchpadDevicename, 0);
	xml.setValue("pad:array", checkboxOscArray.status, 0);
	xml.setValue("pad:frame", checkboxFrame.status, 0);
	//xml.setValue("pad:timestamp", checkboxTimestamp.status, 0);
	xml.setValue("pad:position", checkboxPosition.status, 0);
	//xml.setValue("pad:velocity", checkboxVelocity.status, 0);
	xml.setValue("pad:size", checkboxSize.status, 0);
	//xml.setValue("pad:maxis", checkboxMaxis.status, 0);
	xml.setValue("pad:angle", checkboxAngle.status, 0);

	xml.popRoot();
}

void SettingsMVC::log(){
	ofLog() << "XML: osc:host        = " << oscHost;
	ofLog() << "XML: osc:port        = " << oscPort;

	ofLog() << "pad:devicename  = " << oscTouchpadDevicename;
	ofLog() << "pad:array       = " << checkboxOscArray.status;
	ofLog() << "pad:frame       = " << checkboxFrame.status;
	//ofLog() << "pad:timestamp   = " << checkboxTimestamp.status;
	ofLog() << "pad:position    = " << checkboxPosition.status;
	//ofLog() << "pad:velocity    = " << checkboxVelocity.status;
	ofLog() << "pad:size        = " << checkboxSize.status;
	//ofLog() << "pad:maxis       = " << checkboxMaxis.status;
	ofLog() << "pad:angle       = " << checkboxAngle.status;
}

void SettingsMVC::draw(ofTrueTypeFont font) {
	// ground
	ofEnableAlphaBlending();
	ofSetColor(0, 150);
	ofFill();
	ofRect(10, 30, ofGetWidth()-20, ofGetHeight()-40);
	ofDisableAlphaBlending();
	// Osc settings
	ofSetColor(ofColor::white);
	ofFill();
	font.drawString("OSC SETTINGS", 15, 50);
	// Host: xxx.xxx.xxx.xxx Port: xxxx, Touch Count
	font.drawString("Host: ", 15, 90);
	font.drawString("Port: ", 15, 110);
	font.drawString("Devicename: ", 15, 130);
	font.drawString("[To open the settings xml, press key 's']", 167, 150);

	checkboxOscArray.display();
	checkboxFrame.display();
	//cbTimestamp.display();
	checkboxPosition.display();
	//cbVelocity.display();
	//cbMaxis.display();
	checkboxSize.display();
	checkboxAngle.display();
	// shortcuts
	font.drawString("[Shortcut: 2]", 350, 200);
	font.drawString("[Shortcut: 3]", 350, 220);
	font.drawString("[Shortcut: 4]", 350, 240);
	font.drawString("[Shortcut: 5]", 350, 260);

	// TODO:
	//vera.drawString(ofToString("Number of Devices: ") + ofToString(pad.getNumDevices()), 15, 150);
}

void SettingsMVC::mousePressed(int x, int y) {
	cout << "ViewerSettings mousePressed()";
	/* Check boxes
	 */
	checkboxOscArray.pressed(x, y);
	checkboxFrame.pressed(x, y);
	//cbTimestamp.pressed(x, y);
	checkboxPosition.pressed(x, y);
	//cbVelocity.pressed(x, y);
	//cbMaxis.pressed(x, y);
	checkboxSize.pressed(x, y);
	checkboxAngle.pressed(x, y);
}

void SettingsMVC::keyPressed(int key) {
	switch (key) {
		/* OSC frame
		 */
		case 'w':
			if (checkboxFrame.status == true) {
				checkboxFrame.status = false;
			} else {
				checkboxFrame.status = true;
			}
			//console.addString("Shortcut padFrame: " + ofToString(xmlPadFrame), true);
			break;

			/* OSC timestamp
			 */
			/*case '3':
			 if (settings.padTimestamp == 0) {
			 settings.padTimestamp = 1;
			 } else {
			 settings.padTimestamp = 0;
			 }
			 cbTimestamp.status = settings.padTimestamp;

			 cout << "Shortcut padTimestamp: " << settings.padTimestamp << endl;
			 break;*/

		/* OSC position
		 */
		case 'e':
			if (checkboxPosition.status == true) {
				checkboxPosition.status = false;
			} else {
				checkboxPosition.status = true;
			}
			//console.addString("Shortcut padPosition: " + ofToString(xmlPadPosition), true);
			break;

			/* OSC velocity
			 */
			/*case '5':
			 if (settings.padVelocity == 0) {
			 settings.padVelocity = 1;
			 } else {
			 settings.padVelocity = 0;
			 }
			 cbVelocity.status = settings.padVelocity;

			 cout << "Shortcut padVelocity: " << settings.padVelocity << endl;
			 break;*/

			/* OSC maxis
			 */
			/*case '4':
			 if (settings.padMaxis == 0) {
			 settings.padMaxis = 1;
			 } else {
			 settings.padMaxis = 0;
			 }
			 cbMaxis.status = settings.padMaxis;

			 cout << "Shortcut padMaxis: " << settings.padMaxis << endl;
			 break;*/

		/* OSC maxis
		 */
		case 'r':
			if (checkboxSize.status == true) {
				checkboxSize.status = false;
			} else {
				checkboxSize.status = true;
			}
			//console.addString("Shortcut padSize: " + ofToString(xmlPadSize), true);
			break;

		/* OSC angle
		 */
		case 't':
			if (checkboxAngle.status == true) {
				checkboxAngle.status = false;
			} else {
				checkboxAngle.status = true;
			}
			//console.addString("Shortcut padAngle: " + ofToString(xmlPadAngle), true);
			break;

		default:
			break;
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ctr_socket.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: kz $ $Date: 2006-07-20 16:16:07 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "connector.hxx"
#include <rtl/ustrbuf.hxx>
#include <algorithm>

using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::connection;

namespace stoc_connector {
    template<class T>
    void notifyListeners(SocketConnection * pCon, sal_Bool * notified, T t)
    {
          XStreamListener_hash_set listeners;

        {
            ::osl::MutexGuard guard(pCon->_mutex);
            if(!*notified)
            {
                *notified = sal_True;
                listeners = pCon->_listeners;
            }
        }

        ::std::for_each(listeners.begin(), listeners.end(), t);
    }

    static void callStarted(Reference<XStreamListener> xStreamListener)
    {
        xStreamListener->started();
    }

    struct callError {
        const Any & any;

        callError(const Any & any);

        void operator () (Reference<XStreamListener> xStreamListener);
    };

    callError::callError(const Any & aAny)
        : any(aAny)
    {
    }

    void callError::operator () (Reference<XStreamListener> xStreamListener)
    {
        xStreamListener->error(any);
    }

    static void callClosed(Reference<XStreamListener> xStreamListener)
    {
        xStreamListener->closed();
    }

    SocketConnection::SocketConnection( const OUString &sConnectionDescription ) :
        m_nStatus( 0 ),
        m_sDescription( sConnectionDescription ),
        _started(sal_False),
        _closed(sal_False),
        _error(sal_False)
    {
        // make it unique
        g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
        m_sDescription += OUString( RTL_CONSTASCII_USTRINGPARAM( ",uniqueValue=" ) );
        m_sDescription += OUString::valueOf(
            sal::static_int_cast< sal_Int64 >(
                reinterpret_cast< sal_IntPtr >(&m_socket)),
            10 );
    }

    SocketConnection::~SocketConnection()
    {
        g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
    }

    void SocketConnection::completeConnectionString()
    {
        sal_Int32 nPort;

        nPort = m_socket.getPeerPort();

        OUStringBuffer buf( 256 );
        buf.appendAscii( ",peerPort=" );
        buf.append( (sal_Int32) nPort );
        buf.appendAscii( ",peerHost=" );
        buf.append( m_socket.getPeerHost() );

        buf.appendAscii( ",localPort=" );
        buf.append( (sal_Int32) nPort );
        buf.appendAscii( ",localHost=" );
        buf.append( m_socket.getLocalHost( ) );

        m_sDescription += buf.makeStringAndClear();
    }

    sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {
        if( ! m_nStatus )
        {
            notifyListeners(this, &_started, callStarted);

            if( aReadBytes.getLength() != nBytesToRead )
            {
                aReadBytes.realloc( nBytesToRead );
            }
            sal_Int32 i = m_socket.read( aReadBytes.getArray()  , aReadBytes.getLength() );

            if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None)
            {
                OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - "));
                message += m_socket.getErrorAsString();

                IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

                Any any;
                any <<= ioException;

                notifyListeners(this, &_error, callError(any));

                throw ioException;
            }

            return i;
        }
        else
        {
            OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - connection already closed"));

            IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

            Any any;
            any <<= ioException;

            notifyListeners(this, &_error, callError(any));

            throw ioException;
        }
    }

    void SocketConnection::write( const Sequence < sal_Int8 > &seq )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {
        if( ! m_nStatus )
        {
            if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
            {
                OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - "));
                message += m_socket.getErrorAsString();

                IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

                Any any;
                any <<= ioException;

                notifyListeners(this, &_error, callError(any));

                throw ioException;
            }
        }
        else
        {
            OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - connection already closed"));

            IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

            Any any;
            any <<= ioException;

            notifyListeners(this, &_error, callError(any));

            throw ioException;
        }
    }

    void SocketConnection::flush( )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {

    }

    void SocketConnection::close()
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {
            // ensure that close is called only once
        if( 1 == osl_incrementInterlockedCount( (&m_nStatus) ) )
        {
            m_socket.shutdown();
            notifyListeners(this, &_closed, callClosed);
        }
    }

    OUString SocketConnection::getDescription()
            throw( ::com::sun::star::uno::RuntimeException)
    {
        return m_sDescription;
    }

    // XConnectionBroadcaster
    void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException)
    {
        MutexGuard guard(_mutex);

        _listeners.insert(aListener);
    }

    void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException)
    {
        MutexGuard guard(_mutex);

        _listeners.erase(aListener);
    }
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.10.6); FILE MERGED 2006/09/01 17:31:24 kaib 1.10.6.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ctr_socket.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 23:43:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_io.hxx"

#include "connector.hxx"
#include <rtl/ustrbuf.hxx>
#include <algorithm>

using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::connection;

namespace stoc_connector {
    template<class T>
    void notifyListeners(SocketConnection * pCon, sal_Bool * notified, T t)
    {
          XStreamListener_hash_set listeners;

        {
            ::osl::MutexGuard guard(pCon->_mutex);
            if(!*notified)
            {
                *notified = sal_True;
                listeners = pCon->_listeners;
            }
        }

        ::std::for_each(listeners.begin(), listeners.end(), t);
    }

    static void callStarted(Reference<XStreamListener> xStreamListener)
    {
        xStreamListener->started();
    }

    struct callError {
        const Any & any;

        callError(const Any & any);

        void operator () (Reference<XStreamListener> xStreamListener);
    };

    callError::callError(const Any & aAny)
        : any(aAny)
    {
    }

    void callError::operator () (Reference<XStreamListener> xStreamListener)
    {
        xStreamListener->error(any);
    }

    static void callClosed(Reference<XStreamListener> xStreamListener)
    {
        xStreamListener->closed();
    }

    SocketConnection::SocketConnection( const OUString &sConnectionDescription ) :
        m_nStatus( 0 ),
        m_sDescription( sConnectionDescription ),
        _started(sal_False),
        _closed(sal_False),
        _error(sal_False)
    {
        // make it unique
        g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
        m_sDescription += OUString( RTL_CONSTASCII_USTRINGPARAM( ",uniqueValue=" ) );
        m_sDescription += OUString::valueOf(
            sal::static_int_cast< sal_Int64 >(
                reinterpret_cast< sal_IntPtr >(&m_socket)),
            10 );
    }

    SocketConnection::~SocketConnection()
    {
        g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
    }

    void SocketConnection::completeConnectionString()
    {
        sal_Int32 nPort;

        nPort = m_socket.getPeerPort();

        OUStringBuffer buf( 256 );
        buf.appendAscii( ",peerPort=" );
        buf.append( (sal_Int32) nPort );
        buf.appendAscii( ",peerHost=" );
        buf.append( m_socket.getPeerHost() );

        buf.appendAscii( ",localPort=" );
        buf.append( (sal_Int32) nPort );
        buf.appendAscii( ",localHost=" );
        buf.append( m_socket.getLocalHost( ) );

        m_sDescription += buf.makeStringAndClear();
    }

    sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {
        if( ! m_nStatus )
        {
            notifyListeners(this, &_started, callStarted);

            if( aReadBytes.getLength() != nBytesToRead )
            {
                aReadBytes.realloc( nBytesToRead );
            }
            sal_Int32 i = m_socket.read( aReadBytes.getArray()  , aReadBytes.getLength() );

            if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None)
            {
                OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - "));
                message += m_socket.getErrorAsString();

                IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

                Any any;
                any <<= ioException;

                notifyListeners(this, &_error, callError(any));

                throw ioException;
            }

            return i;
        }
        else
        {
            OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - connection already closed"));

            IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

            Any any;
            any <<= ioException;

            notifyListeners(this, &_error, callError(any));

            throw ioException;
        }
    }

    void SocketConnection::write( const Sequence < sal_Int8 > &seq )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {
        if( ! m_nStatus )
        {
            if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
            {
                OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - "));
                message += m_socket.getErrorAsString();

                IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

                Any any;
                any <<= ioException;

                notifyListeners(this, &_error, callError(any));

                throw ioException;
            }
        }
        else
        {
            OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - connection already closed"));

            IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this)));

            Any any;
            any <<= ioException;

            notifyListeners(this, &_error, callError(any));

            throw ioException;
        }
    }

    void SocketConnection::flush( )
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {

    }

    void SocketConnection::close()
            throw(::com::sun::star::io::IOException,
                  ::com::sun::star::uno::RuntimeException)
    {
            // ensure that close is called only once
        if( 1 == osl_incrementInterlockedCount( (&m_nStatus) ) )
        {
            m_socket.shutdown();
            notifyListeners(this, &_closed, callClosed);
        }
    }

    OUString SocketConnection::getDescription()
            throw( ::com::sun::star::uno::RuntimeException)
    {
        return m_sDescription;
    }

    // XConnectionBroadcaster
    void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException)
    {
        MutexGuard guard(_mutex);

        _listeners.insert(aListener);
    }

    void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException)
    {
        MutexGuard guard(_mutex);

        _listeners.erase(aListener);
    }
}

<|endoftext|>