<commit_before>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include <sys/stat.h>

#include <rocksdb/db.h>
#include <rocksdb/env.h>
#include <rocksdb/options.h>

#include <osquery/filesystem/fileops.h>
#include <osquery/filesystem/filesystem.h>
#include <osquery/flags.h>
#include <osquery/logger.h>
#include <osquery/registry_factory.h>
#include <osquery/utils/conversions/tryto.h>
#include <plugins/database/rocksdb.h>

namespace fs = boost::filesystem;

namespace osquery {

/// Hidden flags created for internal stress testing.
HIDDEN_FLAG(int32, rocksdb_write_buffer, 16, "Max write buffer number");
HIDDEN_FLAG(int32, rocksdb_merge_number, 4, "Min write buffer number to merge");
HIDDEN_FLAG(int32, rocksdb_background_flushes, 4, "Max background flushes");
HIDDEN_FLAG(uint64, rocksdb_buffer_blocks, 256, "Write buffer blocks (4k)");

DECLARE_string(database_path);

/**
 * @brief Track external systems marking the RocksDB database as corrupted.
 *
 * This can be set using the RocksDBDatabasePlugin's static methods.
 * The two primary external systems are the RocksDB logger plugin and tests.
 */
std::atomic<bool> kRocksDBCorruptionIndicator{false};

/// Backing-storage provider for osquery internal/core.
REGISTER_INTERNAL(RocksDBDatabasePlugin, "database", "rocksdb");

void GlogRocksDBLogger::Logv(const char* format, va_list ap) {
  // Convert RocksDB log to string and check if header or level-ed log.
  std::string log_line;
  {
    char buffer[501] = {0};
    vsnprintf(buffer, 500, format, ap);
    va_end(ap);
    if (buffer[0] != '[' || (buffer[1] != 'E' && buffer[1] != 'W')) {
      return;
    }

    log_line = buffer;
  }

  // There is a spurious warning on first open.
  if (log_line.find("Error when reading") == std::string::npos) {
    // RocksDB calls are non-reentrant. Since this callback is made in the
    // context of a RocksDB API call, turn log forwarding off to prevent the
    // logger from trying to make a call back into RocksDB and causing a
    // deadlock.
    LOG(INFO) << "RocksDB: " << log_line;
  }

  // If the callback includes 'Corruption' then set the corruption indicator.
  if (log_line.find("Corruption:") != std::string::npos) {
    RocksDBDatabasePlugin::setCorrupted();
  }
}

Status RocksDBDatabasePlugin::setUp() {
  if (!DatabasePlugin::kDBAllowOpen) {
    LOG(WARNING) << RLOG(1629) << "Not allowed to set up database plugin";
  }

  if (!initialized_) {
    initialized_ = true;
    options_.OptimizeForSmallDb();

    // Set meta-data (mostly) handling options.
    options_.create_if_missing = true;
    options_.create_missing_column_families = true;
    options_.info_log_level = rocksdb::ERROR_LEVEL;
    options_.log_file_time_to_roll = 0;
    options_.keep_log_file_num = 10;
    options_.max_log_file_size = 1024 * 1024 * 1;
    options_.max_open_files = 128;
    options_.stats_dump_period_sec = 0;
    options_.max_manifest_file_size = 1024 * 500;

    // Performance and optimization settings.
    // Use rocksdb::kZSTD to use ZSTD database compression
    options_.compression = rocksdb::kNoCompression;
    options_.compaction_style = rocksdb::kCompactionStyleLevel;
    options_.arena_block_size = (4 * 1024);
    options_.write_buffer_size = (4 * 1024) * FLAGS_rocksdb_buffer_blocks;
    options_.max_write_buffer_number =
        static_cast<int>(FLAGS_rocksdb_write_buffer);
    options_.min_write_buffer_number_to_merge =
        static_cast<int>(FLAGS_rocksdb_merge_number);
    options_.max_background_flushes =
        static_cast<int>(FLAGS_rocksdb_background_flushes);

    // Create an environment to replace the default logger.
    if (logger_ == nullptr) {
      logger_ = std::make_shared<GlogRocksDBLogger>();
    }
    options_.info_log = logger_;

    column_families_.push_back(rocksdb::ColumnFamilyDescriptor(
        rocksdb::kDefaultColumnFamilyName, options_));

    for (const auto& cf_name : kDomains) {
      column_families_.push_back(
          rocksdb::ColumnFamilyDescriptor(cf_name, options_));
    }
  }

  // Consume the current settings.
  // A configuration update may change them, but that does not affect state.
  path_ = fs::path(FLAGS_database_path).make_preferred().string();

  if (pathExists(path_).ok() && !isReadable(path_).ok()) {
    return Status(1, "Cannot read RocksDB path: " + path_);
  }

  if (!DatabasePlugin::kDBChecking) {
    VLOG(1) << "Opening RocksDB handle: " << path_;
  }

  // Tests may trash calls to setUp, make sure subsequent calls do not leak.
  close();

  // Attempt to create a RocksDB instance and handles.
  auto s =
      rocksdb::DB::Open(options_, path_, column_families_, &handles_, &db_);

  if (s.IsCorruption()) {
    // The database is corrupt - try to repair it
    repairDB();
    s = rocksdb::DB::Open(options_, path_, column_families_, &handles_, &db_);
  }

  if (!s.ok() || db_ == nullptr) {
    LOG(INFO) << "Rocksdb open failed (" << s.code() << ":" << s.subcode()
              << ") " << s.ToString();
    if (kDBRequireWrite) {
      // A failed open in R/W mode is a runtime error.
      return Status(1, s.ToString());
    }

    if (!DatabasePlugin::kDBChecking) {
      LOG(INFO) << "Opening RocksDB failed: Continuing with read-only support";
    }
    // Also disable event publishers.
    Flag::updateValue("disable_events", "true");
    read_only_ = true;
  }

  // RocksDB may not create/append a directory with acceptable permissions.
  if (!read_only_ && platformSetSafeDbPerms(path_) == false) {
    return Status(1, "Cannot set permissions on RocksDB path: " + path_);
  }
  return Status(0);
}

void RocksDBDatabasePlugin::tearDown() {
  close();
}

void RocksDBDatabasePlugin::close() {
  WriteLock lock(close_mutex_);
  for (auto handle : handles_) {
    delete handle;
  }
  handles_.clear();

  if (db_ != nullptr) {
    delete db_;
    db_ = nullptr;
  }

  if (isCorrupted()) {
    repairDB();
    setCorrupted(false);
  }
}

bool RocksDBDatabasePlugin::isCorrupted() {
  return kRocksDBCorruptionIndicator;
}

void RocksDBDatabasePlugin::setCorrupted(bool corrupted) {
  kRocksDBCorruptionIndicator = corrupted;
}

void RocksDBDatabasePlugin::repairDB() {
  // Try to backup the existing database.
  auto bpath = path_ + ".backup";
  if (pathExists(bpath).ok()) {
    if (!removePath(bpath).ok()) {
      LOG(ERROR) << "Cannot remove previous RocksDB database backup: " << bpath;
      return;
    } else {
      LOG(WARNING) << "Removed previous RocksDB database backup: " << bpath;
    }
  }

  if (movePath(path_, bpath).ok()) {
    LOG(WARNING) << "Backing up RocksDB database: " << bpath;
  } else {
    LOG(ERROR) << "Cannot backup the RocksDB database: " << bpath;
    return;
  }

  // ROCKSDB_LITE does not have a RepairDB method.
  LOG(WARNING) << "Destroying RocksDB database due to corruption";
}

rocksdb::DB* RocksDBDatabasePlugin::getDB() const {
  return db_;
}

rocksdb::ColumnFamilyHandle* RocksDBDatabasePlugin::getHandleForColumnFamily(
    const std::string& cf) const {
  size_t i = std::find(kDomains.begin(), kDomains.end(), cf) - kDomains.begin();
  if (i != kDomains.size()) {
    return handles_[i];
  } else {
    return nullptr;
  }
}

Status RocksDBDatabasePlugin::get(const std::string& domain,
                                  const std::string& key,
                                  std::string& value) const {
  if (getDB() == nullptr) {
    return Status(1, "Database not opened");
  }
  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto s = getDB()->Get(rocksdb::ReadOptions(), cfh, key, &value);
  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::get(const std::string& domain,
                                  const std::string& key,
                                  int& value) const {
  std::string result;
  auto s = this->get(domain, key, result);
  if (s.ok()) {
    auto expectedValue = tryTo<int>(result);
    if (expectedValue.isError()) {
      return Status::failure("Could not deserialize str to int");
    } else {
      value = expectedValue.take();
    }
  }
  return s;
}
Status RocksDBDatabasePlugin::put(const std::string& domain,
                                  const std::string& key,
                                  const std::string& value) {
  return putBatch(domain, {std::make_pair(key, value)});
}

Status RocksDBDatabasePlugin::putBatch(const std::string& domain,
                                       const DatabaseStringValueList& data) {
  if (read_only_) {
    return Status::success();
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }

  // Events should be fast, and do not need to force syncs.
  auto options = rocksdb::WriteOptions();
  if (kEvents == domain) {
    options.disableWAL = true;
  } else {
    options.sync = true;
  }

  rocksdb::WriteBatch batch;
  for (const auto& p : data) {
    const auto& key = p.first;
    const auto& value = p.second;

    batch.Put(cfh, key, value);
  }

  auto s = getDB()->Write(options, &batch);
  if (s.code() != 0 && s.IsIOError()) {
    // An error occurred, check if it is an IO error and remove the offending
    // specific filename or log name.
    std::string error_string = s.ToString();
    size_t error_pos = error_string.find_last_of(":");
    if (error_pos != std::string::npos) {
      return Status(s.code(), "IOError: " + error_string.substr(error_pos + 2));
    }
  }

  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::put(const std::string& domain,
                                  const std::string& key,
                                  int value) {
  return putBatch(domain, {std::make_pair(key, std::to_string(value))});
}

void RocksDBDatabasePlugin::dumpDatabase() const {}

Status RocksDBDatabasePlugin::remove(const std::string& domain,
                                     const std::string& key) {
  if (read_only_) {
    return Status::success();
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto options = rocksdb::WriteOptions();

  // We could sync here, but large deletes will cause multi-syncs.
  // For example: event record expirations found in an expired index.
  if (kEvents != domain) {
    options.sync = true;
  }
  auto s = getDB()->Delete(options, cfh, key);
  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::removeRange(const std::string& domain,
                                          const std::string& low,
                                          const std::string& high) {
  if (read_only_) {
    return Status::success();
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto options = rocksdb::WriteOptions();

  // We could sync here, but large deletes will cause multi-syncs.
  // For example: event record expirations found in an expired index.
  if (kEvents != domain) {
    options.sync = true;
  }
  auto s = getDB()->DeleteRange(options, cfh, low, high);
  if (low <= high) {
    s = getDB()->Delete(options, cfh, high);
  }
  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::scan(const std::string& domain,
                                   std::vector<std::string>& results,
                                   const std::string& prefix,
                                   size_t max) const {
  if (getDB() == nullptr) {
    return Status(1, "Database not opened");
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto options = rocksdb::ReadOptions();
  options.verify_checksums = false;
  options.fill_cache = false;
  auto it = getDB()->NewIterator(options, cfh);
  if (it == nullptr) {
    return Status(1, "Could not get iterator for " + domain);
  }

  size_t count = 0;
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    auto key = it->key().ToString();
    if (key.find(prefix) == 0) {
      results.push_back(std::move(key));
      if (max > 0 && ++count >= max) {
        break;
      }
    }
  }
  delete it;
  return Status::success();
}
} // namespace osquery
<commit_msg>rocksdb: Remove use of OptimizeForSmallDB in rocksdb plugin (#5797)<commit_after>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include <sys/stat.h>

#include <rocksdb/db.h>
#include <rocksdb/env.h>
#include <rocksdb/options.h>

#include <osquery/filesystem/fileops.h>
#include <osquery/filesystem/filesystem.h>
#include <osquery/flags.h>
#include <osquery/logger.h>
#include <osquery/registry_factory.h>
#include <osquery/utils/conversions/tryto.h>
#include <plugins/database/rocksdb.h>

namespace fs = boost::filesystem;

namespace osquery {

/// Hidden flags created for internal stress testing.
HIDDEN_FLAG(int32, rocksdb_write_buffer, 16, "Max write buffer number");
HIDDEN_FLAG(int32, rocksdb_merge_number, 4, "Min write buffer number to merge");
HIDDEN_FLAG(int32, rocksdb_background_flushes, 4, "Max background flushes");
HIDDEN_FLAG(uint64, rocksdb_buffer_blocks, 256, "Write buffer blocks (4k)");

DECLARE_string(database_path);

/**
 * @brief Track external systems marking the RocksDB database as corrupted.
 *
 * This can be set using the RocksDBDatabasePlugin's static methods.
 * The two primary external systems are the RocksDB logger plugin and tests.
 */
std::atomic<bool> kRocksDBCorruptionIndicator{false};

/// Backing-storage provider for osquery internal/core.
REGISTER_INTERNAL(RocksDBDatabasePlugin, "database", "rocksdb");

void GlogRocksDBLogger::Logv(const char* format, va_list ap) {
  // Convert RocksDB log to string and check if header or level-ed log.
  std::string log_line;
  {
    char buffer[501] = {0};
    vsnprintf(buffer, 500, format, ap);
    va_end(ap);
    if (buffer[0] != '[' || (buffer[1] != 'E' && buffer[1] != 'W')) {
      return;
    }

    log_line = buffer;
  }

  // There is a spurious warning on first open.
  if (log_line.find("Error when reading") == std::string::npos) {
    // RocksDB calls are non-reentrant. Since this callback is made in the
    // context of a RocksDB API call, turn log forwarding off to prevent the
    // logger from trying to make a call back into RocksDB and causing a
    // deadlock.
    LOG(INFO) << "RocksDB: " << log_line;
  }

  // If the callback includes 'Corruption' then set the corruption indicator.
  if (log_line.find("Corruption:") != std::string::npos) {
    RocksDBDatabasePlugin::setCorrupted();
  }
}

Status RocksDBDatabasePlugin::setUp() {
  if (!DatabasePlugin::kDBAllowOpen) {
    LOG(WARNING) << RLOG(1629) << "Not allowed to set up database plugin";
  }

  if (!initialized_) {
    initialized_ = true;

    // Set meta-data (mostly) handling options.
    options_.create_if_missing = true;
    options_.create_missing_column_families = true;
    options_.info_log_level = rocksdb::ERROR_LEVEL;
    options_.log_file_time_to_roll = 0;
    options_.keep_log_file_num = 10;
    options_.max_log_file_size = 1024 * 1024 * 1;
    options_.max_open_files = 128;
    options_.stats_dump_period_sec = 0;
    options_.max_manifest_file_size = 1024 * 500;

    // Performance and optimization settings.
    // Use rocksdb::kZSTD to use ZSTD database compression
    options_.compression = rocksdb::kNoCompression;
    options_.compaction_style = rocksdb::kCompactionStyleLevel;
    options_.arena_block_size = (4 * 1024);
    options_.write_buffer_size = (4 * 1024) * FLAGS_rocksdb_buffer_blocks;
    options_.max_write_buffer_number =
        static_cast<int>(FLAGS_rocksdb_write_buffer);
    options_.min_write_buffer_number_to_merge =
        static_cast<int>(FLAGS_rocksdb_merge_number);
    options_.max_background_flushes =
        static_cast<int>(FLAGS_rocksdb_background_flushes);

    // Create an environment to replace the default logger.
    if (logger_ == nullptr) {
      logger_ = std::make_shared<GlogRocksDBLogger>();
    }
    options_.info_log = logger_;

    column_families_.push_back(rocksdb::ColumnFamilyDescriptor(
        rocksdb::kDefaultColumnFamilyName, options_));

    for (const auto& cf_name : kDomains) {
      column_families_.push_back(
          rocksdb::ColumnFamilyDescriptor(cf_name, options_));
    }
  }

  // Consume the current settings.
  // A configuration update may change them, but that does not affect state.
  path_ = fs::path(FLAGS_database_path).make_preferred().string();

  if (pathExists(path_).ok() && !isReadable(path_).ok()) {
    return Status(1, "Cannot read RocksDB path: " + path_);
  }

  if (!DatabasePlugin::kDBChecking) {
    VLOG(1) << "Opening RocksDB handle: " << path_;
  }

  // Tests may trash calls to setUp, make sure subsequent calls do not leak.
  close();

  // Attempt to create a RocksDB instance and handles.
  auto s =
      rocksdb::DB::Open(options_, path_, column_families_, &handles_, &db_);

  if (s.IsCorruption()) {
    // The database is corrupt - try to repair it
    repairDB();
    s = rocksdb::DB::Open(options_, path_, column_families_, &handles_, &db_);
  }

  if (!s.ok() || db_ == nullptr) {
    LOG(INFO) << "Rocksdb open failed (" << s.code() << ":" << s.subcode()
              << ") " << s.ToString();
    if (kDBRequireWrite) {
      // A failed open in R/W mode is a runtime error.
      return Status(1, s.ToString());
    }

    if (!DatabasePlugin::kDBChecking) {
      LOG(INFO) << "Opening RocksDB failed: Continuing with read-only support";
    }
    // Also disable event publishers.
    Flag::updateValue("disable_events", "true");
    read_only_ = true;
  }

  // RocksDB may not create/append a directory with acceptable permissions.
  if (!read_only_ && platformSetSafeDbPerms(path_) == false) {
    return Status(1, "Cannot set permissions on RocksDB path: " + path_);
  }
  return Status(0);
}

void RocksDBDatabasePlugin::tearDown() {
  close();
}

void RocksDBDatabasePlugin::close() {
  WriteLock lock(close_mutex_);
  for (auto handle : handles_) {
    delete handle;
  }
  handles_.clear();

  if (db_ != nullptr) {
    delete db_;
    db_ = nullptr;
  }

  if (isCorrupted()) {
    repairDB();
    setCorrupted(false);
  }
}

bool RocksDBDatabasePlugin::isCorrupted() {
  return kRocksDBCorruptionIndicator;
}

void RocksDBDatabasePlugin::setCorrupted(bool corrupted) {
  kRocksDBCorruptionIndicator = corrupted;
}

void RocksDBDatabasePlugin::repairDB() {
  // Try to backup the existing database.
  auto bpath = path_ + ".backup";
  if (pathExists(bpath).ok()) {
    if (!removePath(bpath).ok()) {
      LOG(ERROR) << "Cannot remove previous RocksDB database backup: " << bpath;
      return;
    } else {
      LOG(WARNING) << "Removed previous RocksDB database backup: " << bpath;
    }
  }

  if (movePath(path_, bpath).ok()) {
    LOG(WARNING) << "Backing up RocksDB database: " << bpath;
  } else {
    LOG(ERROR) << "Cannot backup the RocksDB database: " << bpath;
    return;
  }

  // ROCKSDB_LITE does not have a RepairDB method.
  LOG(WARNING) << "Destroying RocksDB database due to corruption";
}

rocksdb::DB* RocksDBDatabasePlugin::getDB() const {
  return db_;
}

rocksdb::ColumnFamilyHandle* RocksDBDatabasePlugin::getHandleForColumnFamily(
    const std::string& cf) const {
  size_t i = std::find(kDomains.begin(), kDomains.end(), cf) - kDomains.begin();
  if (i != kDomains.size()) {
    return handles_[i];
  } else {
    return nullptr;
  }
}

Status RocksDBDatabasePlugin::get(const std::string& domain,
                                  const std::string& key,
                                  std::string& value) const {
  if (getDB() == nullptr) {
    return Status(1, "Database not opened");
  }
  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto s = getDB()->Get(rocksdb::ReadOptions(), cfh, key, &value);
  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::get(const std::string& domain,
                                  const std::string& key,
                                  int& value) const {
  std::string result;
  auto s = this->get(domain, key, result);
  if (s.ok()) {
    auto expectedValue = tryTo<int>(result);
    if (expectedValue.isError()) {
      return Status::failure("Could not deserialize str to int");
    } else {
      value = expectedValue.take();
    }
  }
  return s;
}
Status RocksDBDatabasePlugin::put(const std::string& domain,
                                  const std::string& key,
                                  const std::string& value) {
  return putBatch(domain, {std::make_pair(key, value)});
}

Status RocksDBDatabasePlugin::putBatch(const std::string& domain,
                                       const DatabaseStringValueList& data) {
  if (read_only_) {
    return Status::success();
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }

  // Events should be fast, and do not need to force syncs.
  auto options = rocksdb::WriteOptions();
  if (kEvents == domain) {
    options.disableWAL = true;
  } else {
    options.sync = true;
  }

  rocksdb::WriteBatch batch;
  for (const auto& p : data) {
    const auto& key = p.first;
    const auto& value = p.second;

    batch.Put(cfh, key, value);
  }

  auto s = getDB()->Write(options, &batch);
  if (s.code() != 0 && s.IsIOError()) {
    // An error occurred, check if it is an IO error and remove the offending
    // specific filename or log name.
    std::string error_string = s.ToString();
    size_t error_pos = error_string.find_last_of(":");
    if (error_pos != std::string::npos) {
      return Status(s.code(), "IOError: " + error_string.substr(error_pos + 2));
    }
  }

  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::put(const std::string& domain,
                                  const std::string& key,
                                  int value) {
  return putBatch(domain, {std::make_pair(key, std::to_string(value))});
}

void RocksDBDatabasePlugin::dumpDatabase() const {}

Status RocksDBDatabasePlugin::remove(const std::string& domain,
                                     const std::string& key) {
  if (read_only_) {
    return Status::success();
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto options = rocksdb::WriteOptions();

  // We could sync here, but large deletes will cause multi-syncs.
  // For example: event record expirations found in an expired index.
  if (kEvents != domain) {
    options.sync = true;
  }
  auto s = getDB()->Delete(options, cfh, key);
  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::removeRange(const std::string& domain,
                                          const std::string& low,
                                          const std::string& high) {
  if (read_only_) {
    return Status::success();
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto options = rocksdb::WriteOptions();

  // We could sync here, but large deletes will cause multi-syncs.
  // For example: event record expirations found in an expired index.
  if (kEvents != domain) {
    options.sync = true;
  }
  auto s = getDB()->DeleteRange(options, cfh, low, high);
  if (low <= high) {
    s = getDB()->Delete(options, cfh, high);
  }
  return Status(s.code(), s.ToString());
}

Status RocksDBDatabasePlugin::scan(const std::string& domain,
                                   std::vector<std::string>& results,
                                   const std::string& prefix,
                                   size_t max) const {
  if (getDB() == nullptr) {
    return Status(1, "Database not opened");
  }

  auto cfh = getHandleForColumnFamily(domain);
  if (cfh == nullptr) {
    return Status(1, "Could not get column family for " + domain);
  }
  auto options = rocksdb::ReadOptions();
  options.verify_checksums = false;
  options.fill_cache = false;
  auto it = getDB()->NewIterator(options, cfh);
  if (it == nullptr) {
    return Status(1, "Could not get iterator for " + domain);
  }

  size_t count = 0;
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    auto key = it->key().ToString();
    if (key.find(prefix) == 0) {
      results.push_back(std::move(key));
      if (max > 0 && ++count >= max) {
        break;
      }
    }
  }
  delete it;
  return Status::success();
}
} // namespace osquery
<|endoftext|>


<commit_before><commit_msg>fixed a bug with produced items<commit_after><|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_mc.C
/// @brief Initialize the memory controller to take over the DRAM
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP FW Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 1
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{
///
/// @brief Initialize the MC now that DRAM is up
/// @param[in] i_target, the McBIST of the ports of the dram you're training
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start draminit MC");
        FAPI_INF("End draminit MC");
        return fapi2::FAPI2_RC_SUCCESS;
    }
}
<commit_msg>Include .H files in their respective C files to avoid compilation error<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_mc.C
/// @brief Initialize the memory controller to take over the DRAM
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP FW Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 1
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include "p9_mss_draminit_mc.H"

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{
///
/// @brief Initialize the MC now that DRAM is up
/// @param[in] i_target, the McBIST of the ports of the dram you're training
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start draminit MC");
        FAPI_INF("End draminit MC");
        return fapi2::FAPI2_RC_SUCCESS;
    }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file raw_cards.C
/// @brief RDIMM raw card data structure
/// Contains RCW settings per raw card rev
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

// std lib
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H>

namespace mss
{

///
/// @brief raw card A1 settings
///
rcw_settings  rdimm_rc_a1( 0x02, // RC00
                           0x00, // RC01
                           0x0F, // RC06_07
                           0x0C, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6X
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

///
/// @brief raw card B1 settings
/// @note need to verify, copy from b2, need to verify with b1 annex
///
rcw_settings rdimm_rc_b1( 0x02, // RC00
                          0x00, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09 Could be set in eff_config for CKE power DOWN mode
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00);// RCAX

///
/// @brief raw card B2 settings
///
rcw_settings rdimm_rc_b2( 0x02, // RC00
                          0x00, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00);// RCAX

///
/// @brief raw card C1 settings
///
rcw_settings rdimm_rc_c1( 0x02, // RC00
                          0x0C, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00); // RCAX

///
/// @brief raw card C2 settings
/// @note same settings as C1
///
rcw_settings rdimm_rc_c2( 0x02, // RC00
                          0x0C, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00); // RCAX

////
/// @brief raw card for custom dimms
///
rcw_settings rdimm_rc_custom ( 0x02, // RC00
                               0x00, // RC01
                               0x0F, // RC06_07
                               0x0C, // RC09
                               0x0E, // RC0B
                               0x00, // RC0C
                               0x00, // RC0F
                               0x00, // RC1X
                               0x00, // RC2X
                               0x00, // RC4X
                               0x00, // RC5X
                               0x00, // RC6X
                               0x00, // RC8X
                               0x00, // RC9X
                               0x00);// RCAX

////
/// @brief raw card for NVDIMMs
///
rcw_settings rdimm_rc_nvdimm ( 0x00, // RC00
                               0x00, // RC01
                               0x0F, // RC06_07
                               0x00, // RC09
                               0x0E, // RC0B
                               0x00, // RC0C
                               0x00, // RC0F
                               0x00, // RC1X
                               0x00, // RC2X
                               0x00, // RC4X
                               0x00, // RC5X
                               0x00, // RC6X
                               0x00, // RC8X
                               0x00, // RC9X
                               0x00); // RCAX

///
/// @brief raw card VBU settings
///
rcw_settings rdimm_rc_vbu( 0x02, // RC00
                           0x00, // RC01
                           0x0F, // RC06_07
                           0x0C, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6X
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

namespace rdimm
{

const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
{
    // I expect this to grow as Warren M. expects us to have
    // settings for every raw card that JEDEC puts out.  Openpower
    // can't break due to a missing raw card...
    // Note: This list needs to be kept in numerical order of the raw_card_rev
    {raw_card_rev::NVDIMM, rdimm_rc_nvdimm},
    {raw_card_rev::A1, rdimm_rc_a1},
    {raw_card_rev::B1, rdimm_rc_b1},
    {raw_card_rev::C1, rdimm_rc_c1},
    {raw_card_rev::VBU, rdimm_rc_vbu},
    {raw_card_rev::B2, rdimm_rc_b2},
    {raw_card_rev::C2, rdimm_rc_c2},
    {raw_card_rev::CUSTOM, rdimm_rc_custom},
};

}// rdimm
}// mss
<commit_msg>Updates RCD power settings<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file raw_cards.C
/// @brief RDIMM raw card data structure
/// Contains RCW settings per raw card rev
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

// std lib
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H>

namespace mss
{

///
/// @brief raw card A1 settings
///
rcw_settings  rdimm_rc_a1( 0x02, // RC00
                           0x00, // RC01
                           0x0F, // RC06_07
                           0x0C, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6X
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

///
/// @brief raw card B1 settings
/// @note need to verify, copy from b2, need to verify with b1 annex
///
rcw_settings rdimm_rc_b1( 0x02, // RC00
                          0x00, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09 Could be set in eff_config for CKE power DOWN mode
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00);// RCAX

///
/// @brief raw card B2 settings
///
rcw_settings rdimm_rc_b2( 0x02, // RC00
                          0x00, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00);// RCAX

///
/// @brief raw card C1 settings
///
rcw_settings rdimm_rc_c1( 0x02, // RC00
                          0x0C, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00); // RCAX

///
/// @brief raw card C2 settings
/// @note same settings as C1
///
rcw_settings rdimm_rc_c2( 0x02, // RC00
                          0x0C, // RC01
                          0x0F, // RC06_07
                          0x0C, // RC09
                          0x0E, // RC0B
                          0x00, // RC0C
                          0x00, // RC0F
                          0x00, // RC1X
                          0x00, // RC2X
                          0x00, // RC4X
                          0x00, // RC5X
                          0x00, // RC6X
                          0x00, // RC8X
                          0x00, // RC9X
                          0x00); // RCAX

////
/// @brief raw card for custom dimms
///
rcw_settings rdimm_rc_custom ( 0x02, // RC00
                               0x00, // RC01
                               0x0F, // RC06_07
                               0x0C, // RC09
                               0x0E, // RC0B
                               0x00, // RC0C
                               0x00, // RC0F
                               0x00, // RC1X
                               0x00, // RC2X
                               0x00, // RC4X
                               0x00, // RC5X
                               0x00, // RC6X
                               0x00, // RC8X
                               0x00, // RC9X
                               0x00);// RCAX

////
/// @brief raw card for NVDIMMs
///
rcw_settings rdimm_rc_nvdimm ( 0x00, // RC00
                               0x00, // RC01
                               0x0F, // RC06_07
                               0x0C, // RC09
                               0x0E, // RC0B
                               0x00, // RC0C
                               0x00, // RC0F
                               0x00, // RC1X
                               0x00, // RC2X
                               0x00, // RC4X
                               0x00, // RC5X
                               0x00, // RC6X
                               0x00, // RC8X
                               0x00, // RC9X
                               0x00); // RCAX

///
/// @brief raw card VBU settings
///
rcw_settings rdimm_rc_vbu( 0x02, // RC00
                           0x00, // RC01
                           0x0F, // RC06_07
                           0x0C, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6X
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

namespace rdimm
{

const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
{
    // I expect this to grow as Warren M. expects us to have
    // settings for every raw card that JEDEC puts out.  Openpower
    // can't break due to a missing raw card...
    // Note: This list needs to be kept in numerical order of the raw_card_rev
    {raw_card_rev::NVDIMM, rdimm_rc_nvdimm},
    {raw_card_rev::A1, rdimm_rc_a1},
    {raw_card_rev::B1, rdimm_rc_b1},
    {raw_card_rev::C1, rdimm_rc_c1},
    {raw_card_rev::VBU, rdimm_rc_vbu},
    {raw_card_rev::B2, rdimm_rc_b2},
    {raw_card_rev::C2, rdimm_rc_c2},
    {raw_card_rev::CUSTOM, rdimm_rc_custom},
};

}// rdimm
}// mss
<|endoftext|>


<commit_before>using namespace GeFiCa;
// draw V, E distributions saved in an input ROOT file
void drawFields(const char *input="ppc.root")
{
   // Get data from input file
   TFile *file = new TFile(input, "update"); // "update" allows creation of TH3
   PointContactDZ *detector = (PointContactDZ*) file->Get("pcdz");
   TTree *t = detector->GetTree(true);
   const int n = t->GetEntries();

   // fine tune margins, etc.
   gStyle->SetTitleOffset(0.6,"Y");
   gStyle->SetPadRightMargin(0.12);
   gStyle->SetPadLeftMargin(0.07);

   // generate plots
   TCanvas *cv = new TCanvas;
   //cv->SetLogz();
   t->Draw("c1:c2:v","","goff");
   TGraph2D *gv = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   gv->SetName("gv"); gv->SetNpx(500); gv->SetNpy(500); // fine bin histogram
   TH2D *hv = gv->GetHistogram();
   hv->SetTitle(";Radius [cm];Height [cm];Potential [V]");
   hv->GetZaxis()->CenterTitle();
   hv->Draw("colz");

   TCanvas *ce = new TCanvas;
   ce->SetLogz();
   t->Draw("c1:c2:e","","goff");
   TGraph2D *ge = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   ge->SetName("ge"); ge->SetNpx(500); ge->SetNpy(500); // fine bin histogram
   TH2D *he = ge->GetHistogram();
   he->SetTitle(";Radius [cm];Height [cm];E [V/cm]");
   he->GetZaxis()->CenterTitle();
   he->Draw("colz");

   gDebug=1;
   TGraph *g1 = detector->GetFieldLineFrom(3*cm, 1*cm);
   std::cout<<detector->GetE1(3,1);
   g1->Draw("pl");
}
<commit_msg>added E lines<commit_after>using namespace GeFiCa;
// draw V, E distributions saved in an input ROOT file
void drawFields(const char *input="ppc.root")
{
   // Get data from input file
   TFile *file = new TFile(input, "update"); // "update" allows creation of TH3
   PointContactDZ *detector = (PointContactDZ*) file->Get("pcdz");
   TTree *t = detector->GetTree(true);
   const int n = t->GetEntries();

   // fine tune margins, etc.
   gStyle->SetTitleOffset(0.75,"Y");
   gStyle->SetPadRightMargin(0.12);
   gStyle->SetPadLeftMargin(0.08);

   // generate plots
   t->Draw("c1:c2:v","","goff");
   TGraph2D *gv = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   gv->SetName("gv"); gv->SetNpx(500); gv->SetNpy(500); // fine bin histogram
   TH2D *hv = gv->GetHistogram();
   hv->SetTitle(";Radius [cm];Height [cm];Potential [V]");
   hv->GetZaxis()->CenterTitle();
   hv->Draw("colz");

   // draw E field lines
   const int np=12;
   TGraph *gl[np];
   double x[np] = {-25, 0.01, 25, -4, -3, -2, -1, 0.01, 1, 2, 3, 4};
   double y[np] = {49.9, 24.9, 49.9, 2, 2, 2, 2, 2, 2, 2, 2, 2};
   bool positive[np] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1};
   for (int i=0; i<np; i++) {
      gDebug=1;
      gl[i] = detector->GetFieldLineFrom(x[i]*mm, y[i]*mm, positive[i]);
      gDebug=0;
      gl[i]->Draw("l");
   }

   TCanvas *ce = new TCanvas;
   ce->SetLogz();
   t->Draw("c1:c2:e","","goff");
   TGraph2D *ge = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   ge->SetName("ge"); ge->SetNpx(500); ge->SetNpy(500); // fine bin histogram
   TH2D *he = ge->GetHistogram();
   he->SetTitle(";Radius [cm];Height [cm];E [V/cm]");
   he->GetZaxis()->CenterTitle();
   he->Draw("colz");
   for (int i=0; i<np; i++) gl[i]->Draw("p");
}
<|endoftext|>


<commit_before>/// @file
/// @version 2.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <hltypes/hexception.h>
#include <hltypes/hmap.h>
#include <hltypes/hlog.h>
#include <hltypes/hsbase.h>
#include <hltypes/hstream.h>
#include <hltypes/hstring.h>
#include <hltypes/hversion.h>
#include <hlxml/Document.h>
#include <hlxml/Node.h>
#include <hlxml/Property.h>

#include "Deserialize.h"
#include "DeserializeXml.h"
#include "liteser.h"
#include "Serializable.h"
#include "Serialize.h"
#include "SerializeXml.h"
#include "Utility.h"
#include "Variable.h"

#define _LS_HEADER_0 'L'
#define _LS_HEADER_1 'S'

#define HEADER_SIZE 4

#define XML_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
#define LITESER_XML_ROOT_BEGIN hsprintf("<Liteser version=\"%d.%d\">\n\t", _LS_VERSION_MAJOR, _LS_VERSION_MINOR)
#define LITESER_XML_ROOT_END "\t\n</Liteser>"

#define DECLARE_HARRAY_SERIALIZER(type) \
	bool serialize ## suffix(hsbase* stream, harray<type>& value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser Stream"); \
		} \
		_start(stream); \
		stream->writeRaw(header, HEADER_SIZE); \
		Type dumpType; \
		dumpType.assign((VPtr<type>*)NULL); \
		_dumpType(Type::HARRAY); \
		stream->dump(1u); \
		_dumpType(dumpType.value); \
		_dumpHarray(&value); \
		_finish(stream); \
		return true; \
	}

#define DECLARE_HARRAY_DESERIALIZER(type) \
	bool deserialize(hsbase* stream, harray<type>* value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser Stream"); \
		} \
		if (value->size() > 0) \
		{ \
			throw Exception("Output harray is not empty!"); \
		} \
		_start(stream); \
		unsigned char readHeader[HEADER_SIZE]; \
		stream->readRaw(readHeader, HEADER_SIZE); \
		if (readHeader[0] != _LS_HEADER_0 || readHeader[1] != _LS_HEADER_1) \
		{ \
			throw Exception("Invalid header!"); \
		} \
		unsigned char major = readHeader[2]; \
		unsigned char minor = readHeader[3]; \
		_checkVersion(major, minor); \
		if (major > 2 || major == 2 && minor >= 7) \
		{ \
			if (_loadType() != Type::HARRAY) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
			if (stream->loadUint32() != 1) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
			Type subType; \
			subType.assign((VPtr<type>*)NULL); \
			if (_loadType() != subType.value) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
		} \
		_loadHarray(value); \
		_finish(stream); \
		return true; \
	}

#define DECLARE_HARRAY_SERIALIZER_XML(type) \
	bool serialize(hsbase* stream, harray<type>& value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser XML Stream"); \
		} \
		_start(stream); \
		stream->writeLine(XML_HEADER); \
		stream->writeLine(LITESER_XML_ROOT_BEGIN); \
		Type subType; \
		subType.assign((VPtr<type>*)NULL); \
		stream->writeLine("\t<Container type=\"" + hstr(Type::HARRAY) + "\" sub_types=\"" + hstr(subType.value) + "\">"); \
		_indent += "\t"; \
		xml::_dumpHarray(&value); \
		_indent = _indent(0, _indent.size() - 1); \
		stream->writeLine("\t</Container>"); \
		stream->writeLine(LITESER_XML_ROOT_END); \
		_finish(stream); \
		return true; \
	}

#define DECLARE_HARRAY_DESERIALIZER_XML(type) \
	bool deserialize(hsbase* stream, harray<type>* value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser Stream"); \
		} \
		if (value->size() > 0) \
		{ \
			throw Exception("Output harray is not empty!"); \
		} \
		_start(stream); \
		hlxml::Document doc(*stream); \
		hlxml::Node* root = doc.root(); \
		if (*root != "Liteser") \
		{ \
			throw Exception("Invalid header!"); \
		} \
		hstr versionString = root->pstr("version", ""); \
		if (versionString.count(".") != 1) \
		{ \
			throw Exception("Invalid header!"); \
		} \
		hstr majorString; \
		hstr minorString; \
		if (!versionString.split('.', majorString, minorString)) \
		{ \
			throw Exception("Invalid header!"); \
		} \
		unsigned char major = (unsigned char)(int)majorString; \
		unsigned char minor = (unsigned char)(int)minorString; \
		_checkVersion(major, minor); \
		hlxml::Node* node = root; \
		if (major > 2 || major == 2 && minor >= 7) \
		{ \
			node = root->iterChildren(); \
			if (node->next() != NULL || *node != "Container" || node->pstr("type", "00").unhex() != Type::HARRAY) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<\"" #type "\">!"); \
			} \
			Type subType; \
			subType.assign((VPtr<type>*)NULL); \
			harray<hstr> subTypes = node->pstr("sub_types", "00").split(',', -1, true); \
			if (subTypes.size() != 1 || subTypes.first().unhex() != subType.value) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
		} \
		xml::_loadHarray(node, value); \
		_finish(stream); \
		return true; \
	}

namespace liteser
{
	char header[4] = {_LS_HEADER_0, _LS_HEADER_1, (char)_LS_VERSION_MAJOR, (char)_LS_VERSION_MINOR};

	hstr logTag = "liteser";

	bool serialize(hsbase* stream, Serializable* object)
	{
		if (!stream->isOpen())
		{
			throw FileNotOpenException("Liteser Stream");
		}
		// TODO - add exception handling
		_start(stream);
		stream->writeRaw(header, HEADER_SIZE);
		_dumpType(Type::OBJPTR);
		_dump(&object);
		_finish(stream);
		return true;
	}

	DECLARE_HARRAY_SERIALIZER(Serializable*);
	DECLARE_HARRAY_SERIALIZER(char);
	DECLARE_HARRAY_SERIALIZER(unsigned char);
	DECLARE_HARRAY_SERIALIZER(short);
	DECLARE_HARRAY_SERIALIZER(unsigned short);
	DECLARE_HARRAY_SERIALIZER(int);
	DECLARE_HARRAY_SERIALIZER(unsigned int);
	DECLARE_HARRAY_SERIALIZER(int64_t);
	DECLARE_HARRAY_SERIALIZER(uint64_t);
	DECLARE_HARRAY_SERIALIZER(float);
	DECLARE_HARRAY_SERIALIZER(double);
	DECLARE_HARRAY_SERIALIZER(hstr);
	DECLARE_HARRAY_SERIALIZER(hversion);
	DECLARE_HARRAY_SERIALIZER(henum);
	DECLARE_HARRAY_SERIALIZER(grect);
	DECLARE_HARRAY_SERIALIZER(gvec2);
	DECLARE_HARRAY_SERIALIZER(gvec3);

	bool deserialize(hsbase* stream, Serializable** object)
	{
		if (!stream->isOpen())
		{
			throw FileNotOpenException("Liteser Stream");
		}
		if (*object != NULL)
		{
			throw Exception("Given pointer to object for deserialization is not NULL.");
		}
		// TODO - add exception handling
		_start(stream);
		unsigned char readHeader[HEADER_SIZE];
		stream->readRaw(readHeader, HEADER_SIZE);
		if (readHeader[0] != _LS_HEADER_0 || readHeader[1] != _LS_HEADER_1)
		{
			throw Exception("Invalid header!");
		}
		unsigned char major = readHeader[2];
		unsigned char minor = readHeader[3];
		_checkVersion(major, minor);
		if (major > 2 || major == 2 && minor >= 7)
		{
			Type::Value type = _loadType();
			if (type != Type::OBJPTR)
			{
				_finish(stream);
				throw Exception("Cannot load object from file that does not contain an object!");
			}
		}
		_load(object);
		_finish(stream);
		return true;
	}

	DECLARE_HARRAY_DESERIALIZER(Serializable*);
	DECLARE_HARRAY_DESERIALIZER(char);
	DECLARE_HARRAY_DESERIALIZER(unsigned char);
	DECLARE_HARRAY_DESERIALIZER(short);
	DECLARE_HARRAY_DESERIALIZER(unsigned short);
	DECLARE_HARRAY_DESERIALIZER(int);
	DECLARE_HARRAY_DESERIALIZER(unsigned int);
	DECLARE_HARRAY_DESERIALIZER(int64_t);
	DECLARE_HARRAY_DESERIALIZER(uint64_t);
	DECLARE_HARRAY_DESERIALIZER(float);
	DECLARE_HARRAY_DESERIALIZER(double);
	DECLARE_HARRAY_DESERIALIZER(hstr);
	DECLARE_HARRAY_DESERIALIZER(hversion);
	DECLARE_HARRAY_DESERIALIZER(henum);
	DECLARE_HARRAY_DESERIALIZER(grect);
	DECLARE_HARRAY_DESERIALIZER(gvec2);
	DECLARE_HARRAY_DESERIALIZER(gvec3);

	namespace xml
	{
		bool serialize(hsbase* stream, Serializable* object)
		{
			if (!stream->isOpen())
			{
				throw FileNotOpenException("Liteser Stream");
			}
			// TODO - add exception handling
			_start(stream);
			stream->writeLine(XML_HEADER);
			stream->writeLine(LITESER_XML_ROOT_BEGIN);
			xml::_dump(&object);
			stream->writeLine(LITESER_XML_ROOT_END);
			_finish(stream);
			return true;
		}

		DECLARE_HARRAY_SERIALIZER_XML(Serializable*);
		DECLARE_HARRAY_SERIALIZER_XML(char);
		DECLARE_HARRAY_SERIALIZER_XML(unsigned char);
		DECLARE_HARRAY_SERIALIZER_XML(short);
		DECLARE_HARRAY_SERIALIZER_XML(unsigned short);
		DECLARE_HARRAY_SERIALIZER_XML(int);
		DECLARE_HARRAY_SERIALIZER_XML(unsigned int);
		DECLARE_HARRAY_SERIALIZER_XML(int64_t);
		DECLARE_HARRAY_SERIALIZER_XML(uint64_t);
		DECLARE_HARRAY_SERIALIZER_XML(float);
		DECLARE_HARRAY_SERIALIZER_XML(double);
		DECLARE_HARRAY_SERIALIZER_XML(hstr);
		DECLARE_HARRAY_SERIALIZER_XML(hversion);
		DECLARE_HARRAY_SERIALIZER_XML(henum);
		DECLARE_HARRAY_SERIALIZER_XML(grect);
		DECLARE_HARRAY_SERIALIZER_XML(gvec2);
		DECLARE_HARRAY_SERIALIZER_XML(gvec3);

		bool deserialize(hsbase* stream, Serializable** object)
		{
			if (!stream->isOpen())
			{
				throw FileNotOpenException("Liteser Stream");
			}
			if (*object != NULL)
			{
				throw Exception("Given pointer to object for deserialization is not NULL.");
			}
			// TODO - add exception handling
			_start(stream);
			hlxml::Document doc(*stream);
			hlxml::Node* root = doc.root();
			if (*root != "Liteser")
			{
				throw Exception("Invalid header!");
			}
			hstr versionString = root->pstr("version", "");
			if (versionString.count(".") != 1)
			{
				throw Exception("Invalid header!");
			}
			hstr majorString;
			hstr minorString;
			if (!versionString.split('.', majorString, minorString))
			{
				throw Exception("Invalid header!");
			}
			unsigned char major = (unsigned char)(int)majorString;
			unsigned char minor = (unsigned char)(int)minorString;
			_checkVersion(major, minor);
			hlxml::Node* node = root->iterChildren();
			if (major > 2 || major == 2 && minor >= 7)
			{
				if (node->next() != NULL || *node != "Object")
				{
					_finish(stream);
					throw Exception("Cannot load object from file that does not contain an object!");
				}
			}
			xml::_load(node, object);
			_finish(stream);
			return true;
		}

		DECLARE_HARRAY_DESERIALIZER_XML(Serializable*);
		DECLARE_HARRAY_DESERIALIZER_XML(char);
		DECLARE_HARRAY_DESERIALIZER_XML(unsigned char);
		DECLARE_HARRAY_DESERIALIZER_XML(short);
		DECLARE_HARRAY_DESERIALIZER_XML(unsigned short);
		DECLARE_HARRAY_DESERIALIZER_XML(int);
		DECLARE_HARRAY_DESERIALIZER_XML(unsigned int);
		DECLARE_HARRAY_DESERIALIZER_XML(int64_t);
		DECLARE_HARRAY_DESERIALIZER_XML(uint64_t);
		DECLARE_HARRAY_DESERIALIZER_XML(float);
		DECLARE_HARRAY_DESERIALIZER_XML(double);
		DECLARE_HARRAY_DESERIALIZER_XML(hstr);
		DECLARE_HARRAY_DESERIALIZER_XML(hversion);
		DECLARE_HARRAY_DESERIALIZER_XML(henum);
		DECLARE_HARRAY_DESERIALIZER_XML(grect);
		DECLARE_HARRAY_DESERIALIZER_XML(gvec2);
		DECLARE_HARRAY_DESERIALIZER_XML(gvec3);

	}

	bool clone(Serializable* input, Serializable** output)
	{
		if (*output != NULL)
		{
			throw Exception("Output does not point to NULL!");
		}
		hstream stream;
		_start(&stream);
		_dump(&input);
		_finish(&stream);
		stream.rewind();
		_start(&stream);
		_load(output);
		_finish(&stream);
		return true;
	}

}
<commit_msg>- small fix<commit_after>/// @file
/// @version 2.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <hltypes/hexception.h>
#include <hltypes/hmap.h>
#include <hltypes/hlog.h>
#include <hltypes/hsbase.h>
#include <hltypes/hstream.h>
#include <hltypes/hstring.h>
#include <hltypes/hversion.h>
#include <hlxml/Document.h>
#include <hlxml/Node.h>
#include <hlxml/Property.h>

#include "Deserialize.h"
#include "DeserializeXml.h"
#include "liteser.h"
#include "Serializable.h"
#include "Serialize.h"
#include "SerializeXml.h"
#include "Utility.h"
#include "Variable.h"

#define _LS_HEADER_0 'L'
#define _LS_HEADER_1 'S'

#define HEADER_SIZE 4

#define XML_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
#define LITESER_XML_ROOT_BEGIN hsprintf("<Liteser version=\"%d.%d\">\n\t", _LS_VERSION_MAJOR, _LS_VERSION_MINOR)
#define LITESER_XML_ROOT_END "\t\n</Liteser>"

#define DECLARE_HARRAY_SERIALIZER(type) \
	bool serialize(hsbase* stream, harray<type>& value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser Stream"); \
		} \
		_start(stream); \
		stream->writeRaw(header, HEADER_SIZE); \
		Type dumpType; \
		dumpType.assign((VPtr<type>*)NULL); \
		_dumpType(Type::HARRAY); \
		stream->dump(1u); \
		_dumpType(dumpType.value); \
		_dumpHarray(&value); \
		_finish(stream); \
		return true; \
	}

#define DECLARE_HARRAY_DESERIALIZER(type) \
	bool deserialize(hsbase* stream, harray<type>* value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser Stream"); \
		} \
		if (value->size() > 0) \
		{ \
			throw Exception("Output harray is not empty!"); \
		} \
		_start(stream); \
		unsigned char readHeader[HEADER_SIZE]; \
		stream->readRaw(readHeader, HEADER_SIZE); \
		if (readHeader[0] != _LS_HEADER_0 || readHeader[1] != _LS_HEADER_1) \
		{ \
			throw Exception("Invalid header!"); \
		} \
		unsigned char major = readHeader[2]; \
		unsigned char minor = readHeader[3]; \
		_checkVersion(major, minor); \
		if (major > 2 || major == 2 && minor >= 7) \
		{ \
			if (_loadType() != Type::HARRAY) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
			if (stream->loadUint32() != 1) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
			Type subType; \
			subType.assign((VPtr<type>*)NULL); \
			if (_loadType() != subType.value) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
		} \
		_loadHarray(value); \
		_finish(stream); \
		return true; \
	}

#define DECLARE_HARRAY_SERIALIZER_XML(type) \
	bool serialize(hsbase* stream, harray<type>& value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser XML Stream"); \
		} \
		_start(stream); \
		stream->writeLine(XML_HEADER); \
		stream->writeLine(LITESER_XML_ROOT_BEGIN); \
		Type subType; \
		subType.assign((VPtr<type>*)NULL); \
		stream->writeLine("\t<Container type=\"" + hstr(Type::HARRAY) + "\" sub_types=\"" + hstr(subType.value) + "\">"); \
		_indent += "\t"; \
		xml::_dumpHarray(&value); \
		_indent = _indent(0, _indent.size() - 1); \
		stream->writeLine("\t</Container>"); \
		stream->writeLine(LITESER_XML_ROOT_END); \
		_finish(stream); \
		return true; \
	}

#define DECLARE_HARRAY_DESERIALIZER_XML(type) \
	bool deserialize(hsbase* stream, harray<type>* value) \
	{ \
		if (!stream->isOpen()) \
		{ \
			throw FileNotOpenException("Liteser Stream"); \
		} \
		if (value->size() > 0) \
		{ \
			throw Exception("Output harray is not empty!"); \
		} \
		_start(stream); \
		hlxml::Document doc(*stream); \
		hlxml::Node* root = doc.root(); \
		if (*root != "Liteser") \
		{ \
			throw Exception("Invalid header!"); \
		} \
		hstr versionString = root->pstr("version", ""); \
		if (versionString.count(".") != 1) \
		{ \
			throw Exception("Invalid header!"); \
		} \
		hstr majorString; \
		hstr minorString; \
		if (!versionString.split('.', majorString, minorString)) \
		{ \
			throw Exception("Invalid header!"); \
		} \
		unsigned char major = (unsigned char)(int)majorString; \
		unsigned char minor = (unsigned char)(int)minorString; \
		_checkVersion(major, minor); \
		hlxml::Node* node = root; \
		if (major > 2 || major == 2 && minor >= 7) \
		{ \
			node = root->iterChildren(); \
			if (node->next() != NULL || *node != "Container" || node->pstr("type", "00").unhex() != Type::HARRAY) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<\"" #type "\">!"); \
			} \
			Type subType; \
			subType.assign((VPtr<type>*)NULL); \
			harray<hstr> subTypes = node->pstr("sub_types", "00").split(',', -1, true); \
			if (subTypes.size() != 1 || subTypes.first().unhex() != subType.value) \
			{ \
				_finish(stream); \
				throw Exception("Cannot load object from file that does not contain a harray<" #type ">!"); \
			} \
		} \
		xml::_loadHarray(node, value); \
		_finish(stream); \
		return true; \
	}

namespace liteser
{
	char header[4] = {_LS_HEADER_0, _LS_HEADER_1, (char)_LS_VERSION_MAJOR, (char)_LS_VERSION_MINOR};

	hstr logTag = "liteser";

	bool serialize(hsbase* stream, Serializable* object)
	{
		if (!stream->isOpen())
		{
			throw FileNotOpenException("Liteser Stream");
		}
		// TODO - add exception handling
		_start(stream);
		stream->writeRaw(header, HEADER_SIZE);
		_dumpType(Type::OBJPTR);
		_dump(&object);
		_finish(stream);
		return true;
	}

	DECLARE_HARRAY_SERIALIZER(Serializable*);
	DECLARE_HARRAY_SERIALIZER(char);
	DECLARE_HARRAY_SERIALIZER(unsigned char);
	DECLARE_HARRAY_SERIALIZER(short);
	DECLARE_HARRAY_SERIALIZER(unsigned short);
	DECLARE_HARRAY_SERIALIZER(int);
	DECLARE_HARRAY_SERIALIZER(unsigned int);
	DECLARE_HARRAY_SERIALIZER(int64_t);
	DECLARE_HARRAY_SERIALIZER(uint64_t);
	DECLARE_HARRAY_SERIALIZER(float);
	DECLARE_HARRAY_SERIALIZER(double);
	DECLARE_HARRAY_SERIALIZER(hstr);
	DECLARE_HARRAY_SERIALIZER(hversion);
	DECLARE_HARRAY_SERIALIZER(henum);
	DECLARE_HARRAY_SERIALIZER(grect);
	DECLARE_HARRAY_SERIALIZER(gvec2);
	DECLARE_HARRAY_SERIALIZER(gvec3);

	bool deserialize(hsbase* stream, Serializable** object)
	{
		if (!stream->isOpen())
		{
			throw FileNotOpenException("Liteser Stream");
		}
		if (*object != NULL)
		{
			throw Exception("Given pointer to object for deserialization is not NULL.");
		}
		// TODO - add exception handling
		_start(stream);
		unsigned char readHeader[HEADER_SIZE];
		stream->readRaw(readHeader, HEADER_SIZE);
		if (readHeader[0] != _LS_HEADER_0 || readHeader[1] != _LS_HEADER_1)
		{
			throw Exception("Invalid header!");
		}
		unsigned char major = readHeader[2];
		unsigned char minor = readHeader[3];
		_checkVersion(major, minor);
		if (major > 2 || (major == 2 && minor >= 7))
		{
			Type::Value type = _loadType();
			if (type != Type::OBJPTR)
			{
				_finish(stream);
				throw Exception("Cannot load object from file that does not contain an object!");
			}
		}
		_load(object);
		_finish(stream);
		return true;
	}

	DECLARE_HARRAY_DESERIALIZER(Serializable*);
	DECLARE_HARRAY_DESERIALIZER(char);
	DECLARE_HARRAY_DESERIALIZER(unsigned char);
	DECLARE_HARRAY_DESERIALIZER(short);
	DECLARE_HARRAY_DESERIALIZER(unsigned short);
	DECLARE_HARRAY_DESERIALIZER(int);
	DECLARE_HARRAY_DESERIALIZER(unsigned int);
	DECLARE_HARRAY_DESERIALIZER(int64_t);
	DECLARE_HARRAY_DESERIALIZER(uint64_t);
	DECLARE_HARRAY_DESERIALIZER(float);
	DECLARE_HARRAY_DESERIALIZER(double);
	DECLARE_HARRAY_DESERIALIZER(hstr);
	DECLARE_HARRAY_DESERIALIZER(hversion);
	DECLARE_HARRAY_DESERIALIZER(henum);
	DECLARE_HARRAY_DESERIALIZER(grect);
	DECLARE_HARRAY_DESERIALIZER(gvec2);
	DECLARE_HARRAY_DESERIALIZER(gvec3);

	namespace xml
	{
		bool serialize(hsbase* stream, Serializable* object)
		{
			if (!stream->isOpen())
			{
				throw FileNotOpenException("Liteser Stream");
			}
			// TODO - add exception handling
			_start(stream);
			stream->writeLine(XML_HEADER);
			stream->writeLine(LITESER_XML_ROOT_BEGIN);
			xml::_dump(&object);
			stream->writeLine(LITESER_XML_ROOT_END);
			_finish(stream);
			return true;
		}

		DECLARE_HARRAY_SERIALIZER_XML(Serializable*);
		DECLARE_HARRAY_SERIALIZER_XML(char);
		DECLARE_HARRAY_SERIALIZER_XML(unsigned char);
		DECLARE_HARRAY_SERIALIZER_XML(short);
		DECLARE_HARRAY_SERIALIZER_XML(unsigned short);
		DECLARE_HARRAY_SERIALIZER_XML(int);
		DECLARE_HARRAY_SERIALIZER_XML(unsigned int);
		DECLARE_HARRAY_SERIALIZER_XML(int64_t);
		DECLARE_HARRAY_SERIALIZER_XML(uint64_t);
		DECLARE_HARRAY_SERIALIZER_XML(float);
		DECLARE_HARRAY_SERIALIZER_XML(double);
		DECLARE_HARRAY_SERIALIZER_XML(hstr);
		DECLARE_HARRAY_SERIALIZER_XML(hversion);
		DECLARE_HARRAY_SERIALIZER_XML(henum);
		DECLARE_HARRAY_SERIALIZER_XML(grect);
		DECLARE_HARRAY_SERIALIZER_XML(gvec2);
		DECLARE_HARRAY_SERIALIZER_XML(gvec3);

		bool deserialize(hsbase* stream, Serializable** object)
		{
			if (!stream->isOpen())
			{
				throw FileNotOpenException("Liteser Stream");
			}
			if (*object != NULL)
			{
				throw Exception("Given pointer to object for deserialization is not NULL.");
			}
			// TODO - add exception handling
			_start(stream);
			hlxml::Document doc(*stream);
			hlxml::Node* root = doc.root();
			if (*root != "Liteser")
			{
				throw Exception("Invalid header!");
			}
			hstr versionString = root->pstr("version", "");
			if (versionString.count(".") != 1)
			{
				throw Exception("Invalid header!");
			}
			hstr majorString;
			hstr minorString;
			if (!versionString.split('.', majorString, minorString))
			{
				throw Exception("Invalid header!");
			}
			unsigned char major = (unsigned char)(int)majorString;
			unsigned char minor = (unsigned char)(int)minorString;
			_checkVersion(major, minor);
			hlxml::Node* node = root->iterChildren();
			if (major > 2 || (major == 2 && minor >= 7))
			{
				if (node->next() != NULL || *node != "Object")
				{
					_finish(stream);
					throw Exception("Cannot load object from file that does not contain an object!");
				}
			}
			xml::_load(node, object);
			_finish(stream);
			return true;
		}

		DECLARE_HARRAY_DESERIALIZER_XML(Serializable*);
		DECLARE_HARRAY_DESERIALIZER_XML(char);
		DECLARE_HARRAY_DESERIALIZER_XML(unsigned char);
		DECLARE_HARRAY_DESERIALIZER_XML(short);
		DECLARE_HARRAY_DESERIALIZER_XML(unsigned short);
		DECLARE_HARRAY_DESERIALIZER_XML(int);
		DECLARE_HARRAY_DESERIALIZER_XML(unsigned int);
		DECLARE_HARRAY_DESERIALIZER_XML(int64_t);
		DECLARE_HARRAY_DESERIALIZER_XML(uint64_t);
		DECLARE_HARRAY_DESERIALIZER_XML(float);
		DECLARE_HARRAY_DESERIALIZER_XML(double);
		DECLARE_HARRAY_DESERIALIZER_XML(hstr);
		DECLARE_HARRAY_DESERIALIZER_XML(hversion);
		DECLARE_HARRAY_DESERIALIZER_XML(henum);
		DECLARE_HARRAY_DESERIALIZER_XML(grect);
		DECLARE_HARRAY_DESERIALIZER_XML(gvec2);
		DECLARE_HARRAY_DESERIALIZER_XML(gvec3);

	}

	bool clone(Serializable* input, Serializable** output)
	{
		if (*output != NULL)
		{
			throw Exception("Output does not point to NULL!");
		}
		hstream stream;
		_start(&stream);
		_dump(&input);
		_finish(&stream);
		stream.rewind();
		_start(&stream);
		_load(output);
		_finish(&stream);
		return true;
	}

}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkProgressBar.h"
#include <qprogressbar.h>
#include <mitkProgressBar.h>
#include <qmainwindow.h>
#include <itkObjectFactory.h>

/**
 * Reset the progress bar. The progress bar "rewinds" and shows no progress.
 */
void QmitkProgressBar::Reset()
{
  this->reset();
  this->hide();
  m_TotalSteps = 0;
  m_Progress = 0;
}

/**
 * Sets whether the current progress value is displayed.
 */
void QmitkProgressBar::SetPercentageVisible(bool visible)
{
  this->setPercentageVisible(visible);
}

/**
 *Documentation
 *@brief Adds steps to totalSteps.
 */
void QmitkProgressBar::AddStepsToDo(unsigned int steps)
{
  m_TotalSteps += steps;
  this->setProgress(m_Progress, m_TotalSteps);
  this->show();
}

/**
 *Documentation
 *@brief Sets the current amount of progress to current progress + steps.
 *@param: steps the number of steps done since last Progress(int steps) call.
 */
void QmitkProgressBar::Progress(unsigned int steps)
{
  m_Progress += steps;
  this->setProgress(m_Progress);
  this->show();

  if (m_Progress >= m_TotalSteps)
    Reset();
}

QmitkProgressBar::QmitkProgressBar(QWidget * parent, const char * name, WFlags f)
:QProgressBar(parent, name, f), ProgressBarImplementation()
{
    m_TotalSteps = 0;
    m_Progress = 0;
    this->hide();
    this->SetPercentageVisible(true);
    mitk::ProgressBar::SetImplementationInstance(this);
}

QmitkProgressBar::~QmitkProgressBar()
{
}
<commit_msg>Add qApp->processEvents(), trying to fix bug #357<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkProgressBar.h"
#include <qprogressbar.h>
#include <mitkProgressBar.h>
//#include <qmainwindow.h>
#include <qapplication.h>
//#include <itkObjectFactory.h>

/**
 * Reset the progress bar. The progress bar "rewinds" and shows no progress.
 */
void QmitkProgressBar::Reset()
{
  this->reset();
  this->hide();
  m_TotalSteps = 0;
  m_Progress = 0;
}

/**
 * Sets whether the current progress value is displayed.
 */
void QmitkProgressBar::SetPercentageVisible(bool visible)
{
  this->setPercentageVisible(visible);
}

/**
 *Documentation
 *@brief Adds steps to totalSteps.
 */
void QmitkProgressBar::AddStepsToDo(unsigned int steps)
{
  m_TotalSteps += steps;
  this->setProgress(m_Progress, m_TotalSteps);
  this->show();
  qApp->processEvents();
}

/**
 *Documentation
 *@brief Sets the current amount of progress to current progress + steps.
 *@param: steps the number of steps done since last Progress(int steps) call.
 */
void QmitkProgressBar::Progress(unsigned int steps)
{
  m_Progress += steps;
  this->setProgress(m_Progress);
  this->show();

  if (m_Progress >= m_TotalSteps)
    Reset();

  qApp->processEvents();
}

QmitkProgressBar::QmitkProgressBar(QWidget * parent, const char * name, WFlags f)
:QProgressBar(parent, name, f), ProgressBarImplementation()
{
    m_TotalSteps = 0;
    m_Progress = 0;
    this->hide();
    this->SetPercentageVisible(true);
    mitk::ProgressBar::SetImplementationInstance(this);
}

QmitkProgressBar::~QmitkProgressBar()
{
}
<|endoftext|>