text:
// Copyright (c) 2015, Baidu.com, Inc. All Rights Reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Author: yanshiguang02@baidu.com

#include "namespace.h"

#include <fcntl.h>
#include <gflags/gflags.h>
#include <leveldb/db.h>
#include <leveldb/cache.h>
#include <leveldb/write_batch.h>
#include <common/logging.h>
#include <common/timer.h>
#include <common/util.h>
#include <common/atomic.h>
#include <common/string_util.h>
#include <boost/bind.hpp>

#include "nameserver/sync.h"

DECLARE_string(namedb_path);
DECLARE_int64(namedb_cache_size);
DECLARE_int32(default_replica_num);
DECLARE_int32(block_id_allocation_size);
DECLARE_bool(check_orphan);

const int64_t kRootEntryid = 1;

namespace baidu {
namespace bfs {

NameSpace::NameSpace(bool standalone): version_(0), last_entry_id_(1),
    block_id_upbound_(1), next_block_id_(1) {
    leveldb::Options options;
    options.create_if_missing = true;
    options.block_cache = leveldb::NewLRUCache(FLAGS_namedb_cache_size*1024L*1024L);
    leveldb::Status s = leveldb::DB::Open(options, FLAGS_namedb_path, &db_);
    if (!s.ok()) {
        db_ = NULL;
        LOG(FATAL, "Open leveldb fail: %s\n", s.ToString().c_str());
        return;
    }
    if (standalone) {
        Activate(NULL, NULL);
    }
}

void NameSpace::Activate(boost::function<void (const FileInfo&)> callback, NameServerLog* log) {
    std::string version_key(8, 0);
    version_key.append("version");
    std::string version_str;
    leveldb::Status s = db_->Get(leveldb::ReadOptions(), version_key, &version_str);
    if (s.ok()) {
        if (version_str.size() != sizeof(int64_t)) {
            LOG(FATAL, "Bad namespace version len= %lu.", version_str.size());
        }
        version_ = *(reinterpret_cast<int64_t*>(&version_str[0]));
        LOG(INFO, "Load namespace version: %ld ", version_);
    } else {
        version_ = common::timer::get_micros();
        version_str.resize(8);
        *(reinterpret_cast<int64_t*>(&version_str[0])) = version_;

        leveldb::Status s = db_->Put(leveldb::WriteOptions(), version_key, version_str);
        if (!s.ok()) {
            LOG(FATAL, "Write NameSpace version failed %s", s.ToString().c_str());
        }
        EncodeLog(log, kSyncWrite, version_key, version_str);
        LOG(INFO, "Create new namespace version: %ld ", version_);
    }
    SetupRoot();
    RebuildBlockMap(callback);
    InitBlockIdUpbound(log);
}
NameSpace::~NameSpace() {
    delete db_;
    db_ = NULL;
}

int64_t NameSpace::Version() const {
    return version_;
}

bool NameSpace::IsDir(int type) {
    return (type & (1<<9));
}

void NameSpace::EncodingStoreKey(int64_t entry_id,
                                 const std::string& path,
                                 std::string* key_str) {
    key_str->resize(8);
    common::util::EncodeBigEndian(&(*key_str)[0], (uint64_t)entry_id);
    key_str->append(path);
}

void NameSpace::DecodingStoreKey(const std::string& key_str,
                                 int64_t* entry_id,
                                 std::string* path) {
    assert(key_str.size() >= 8UL);
    if (entry_id) {
        *entry_id = common::util::DecodeBigEndian64(key_str.c_str());
    }
    if (path) {
        path->assign(key_str, 8, std::string::npos);
    }
}

bool NameSpace::GetFromStore(const std::string& key, FileInfo* info) {
    std::string value;
    leveldb::Status s = db_->Get(leveldb::ReadOptions(), key, &value);
    if (!s.ok()) {
        LOG(DEBUG, "GetFromStore get fail %s %s",
            key.substr(8).c_str(), s.ToString().c_str());
        return false;
    }
    if (!info->ParseFromString(value)) {
        LOG(WARNING, "GetFromStore parse fail %s", key.substr(8).c_str());
        return false;
    }
    return true;
}

void NameSpace::SetupRoot() {
    root_path_.set_entry_id(kRootEntryid);
    root_path_.set_name("");
    root_path_.set_parent_entry_id(kRootEntryid);
    root_path_.set_type(01755);
    root_path_.set_ctime(static_cast<uint32_t>(version_/1000000));
}
/// New SplitPath
/// /home/dirx/filex
///       diry/filey
/// /tmp/filez
/// 1home -> 2
/// 1tmp -> 3
/// 2dirx -> 4
/// 2diry -> 5
/// 3filez -> 6
/// 4filex -> 7
/// 5filey -> 8
bool NameSpace::LookUp(const std::string& path, FileInfo* info) {
    if (path == "/") {
        info->CopyFrom(root_path_);
        return true;
    }
    std::vector<std::string> paths;
    if (!common::util::SplitPath(path, &paths) || path.empty()) {
        return false;
    }
    int64_t parent_id = kRootEntryid;
    int64_t entry_id = kRootEntryid;
    for (size_t i = 0; i < paths.size(); i++) {
        if (!LookUp(entry_id, paths[i], info)) {
            return false;
        }
        parent_id = entry_id;
        entry_id = info->entry_id();
        LOG(DEBUG, "LookUp %s entry_id= E%ld ", paths[i].c_str(), entry_id);
    }
    info->set_name(paths[paths.size()-1]);
    info->set_parent_entry_id(parent_id);
    LOG(INFO, "LookUp %s return %s", path.c_str(), info->name().c_str());
    return true;
}

bool NameSpace::LookUp(int64_t parent_id, const std::string& name, FileInfo* info) {
    std::string key_str;
    EncodingStoreKey(parent_id, name, &key_str);
    if (!GetFromStore(key_str, info)) {
        LOG(INFO, "LookUp E%ld %s return false", parent_id, name.c_str());
        return false;
    }
    LOG(DEBUG, "LookUp E%ld %s return true", parent_id, name.c_str());
    return true;
}

bool NameSpace::DeleteFileInfo(const std::string file_key, NameServerLog* log) {
    leveldb::Status s = db_->Delete(leveldb::WriteOptions(), file_key);
    if (!s.ok()) {
        return false;
    }
    EncodeLog(log,kSyncDelete, file_key, "");
    return true;
}
bool NameSpace::UpdateFileInfo(const FileInfo& file_info, NameServerLog* log) {
    FileInfo file_info_for_ldb;
    file_info_for_ldb.CopyFrom(file_info);
    file_info_for_ldb.clear_cs_addrs();

    std::string file_key;
    EncodingStoreKey(file_info_for_ldb.parent_entry_id(), file_info_for_ldb.name(), &file_key);
    std::string infobuf_for_ldb, infobuf_for_sync;
    file_info_for_ldb.SerializeToString(&infobuf_for_ldb);
    file_info.SerializeToString(&infobuf_for_sync);

    leveldb::Status s = db_->Put(leveldb::WriteOptions(), file_key, infobuf_for_ldb);
    if (!s.ok()) {
        LOG(WARNING, "NameSpace write to db fail: %s", s.ToString().c_str());
        return false;
    }
    EncodeLog(log, kSyncWrite, file_key, infobuf_for_ldb);
    return true;
};

bool NameSpace::GetFileInfo(const std::string& path, FileInfo* file_info) {
    return LookUp(path, file_info);
}

StatusCode NameSpace::CreateFile(const std::string& path, int flags, int mode, int replica_num,
                                 std::vector<int64_t>* blocks_to_remove,
                                 NameServerLog* log) {
    std::vector<std::string> paths;
    if (!common::util::SplitPath(path, &paths)) {
        LOG(INFO, "CreateFile split fail %s", path.c_str());
        return kBadParameter;
    }

    /// Find parent directory, create if not exist.
    FileInfo file_info;
    int64_t parent_id = kRootEntryid;
    int depth = paths.size();
    std::string info_value;
    for (int i=0; i < depth-1; ++i) {
        if (!LookUp(parent_id, paths[i], &file_info)) {
            file_info.set_type((1<<9)|0755);
            file_info.set_ctime(time(NULL));
            file_info.set_entry_id(common::atomic_add64(&last_entry_id_, 1) + 1);
            file_info.SerializeToString(&info_value);
            std::string key_str;
            EncodingStoreKey(parent_id, paths[i], &key_str);
            leveldb::Status s = db_->Put(leveldb::WriteOptions(), key_str, info_value);
            assert(s.ok());
            EncodeLog(log, kSyncWrite, key_str, info_value);
            LOG(INFO, "Create path recursively: %s E%ld ", paths[i].c_str(), file_info.entry_id());
        } else {
            if (!IsDir(file_info.type())) {
                LOG(INFO, "Create path fail: %s is not a directory", paths[i].c_str());
                return kBadParameter;
            }
        }
        parent_id = file_info.entry_id();
    }

    const std::string& fname = paths[depth-1];
    bool exist = LookUp(parent_id, fname, &file_info);
    if (exist) {
        if ((flags & O_TRUNC) == 0) {
            LOG(INFO, "CreateFile %s fail: already exist!", fname.c_str());
            return kFileExists;
        } else {
            if (IsDir(file_info.type())) {
                LOG(INFO, "CreateFile %s fail: directory with same name exist", fname.c_str());
                return kFileExists;
            }
            for (int i = 0; i < file_info.blocks_size(); i++) {
                blocks_to_remove->push_back(file_info.blocks(i));
            }
        }
    }
    file_info.set_type(((1 << 10) - 1) & mode);
    file_info.set_entry_id(common::atomic_add64(&last_entry_id_, 1) + 1);
    file_info.set_ctime(time(NULL));
    file_info.set_replicas(replica_num <= 0 ? FLAGS_default_replica_num : replica_num);
    //file_info.add_blocks();
    file_info.SerializeToString(&info_value);
    std::string file_key;
    EncodingStoreKey(parent_id, fname, &file_key);
    leveldb::Status s = db_->Put(leveldb::WriteOptions(), file_key, info_value);
    if (s.ok()) {
        LOG(INFO, "CreateFile %s E%ld ", path.c_str(), file_info.entry_id());
        EncodeLog(log, kSyncWrite, file_key, info_value);
        return kOK;
    } else {
        LOG(WARNING, "CreateFile %s fail: db put fail %s", path.c_str(), s.ToString().c_str());
        return kUpdateError;
    }
}

StatusCode NameSpace::ListDirectory(const std::string& path,
                             google::protobuf::RepeatedPtrField<FileInfo>* outputs) {
    outputs->Clear();
    FileInfo info;
    if (!LookUp(path, &info)) {
        return kNsNotFound;
    }
    if (!IsDir(info.type())) {
        FileInfo* file_info = outputs->Add();
        file_info->CopyFrom(info);
        //for a file, name should be empty because it's a relative path
        file_info->clear_name();
        LOG(INFO, "List %s return %ld items", path.c_str(), outputs->size());
        return kOK;
    }
    int64_t entry_id = info.entry_id();
    LOG(DEBUG, "ListDirectory entry_id= E%ld ", entry_id);
    common::timer::AutoTimer at1(100, "ListDirectory iterate", path.c_str());
    std::string key_start, key_end;
    EncodingStoreKey(entry_id, "", &key_start);
    EncodingStoreKey(entry_id + 1, "", &key_end);
    leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
    for (it->Seek(key_start); it->Valid(); it->Next()) {
        leveldb::Slice key = it->key();
        if (key.compare(key_end)>=0) {
            break;
        }
        FileInfo* file_info = outputs->Add();
        bool ret = file_info->ParseFromArray(it->value().data(), it->value().size());
        assert(ret);
        file_info->set_name(std::string(key.data() + 8, key.size() - 8));
        LOG(DEBUG, "List %s return %s[%s]",
            path.c_str(), file_info->name().c_str(),
            common::DebugString(key.ToString()).c_str());
    }
    LOG(INFO, "List return %ld items", outputs->size());
    delete it;
    return kOK;
}

StatusCode NameSpace::Rename(const std::string& old_path,
                      const std::string& new_path,
                      bool* need_unlink,
                      FileInfo* remove_file,
                      NameServerLog* log) {
    *need_unlink = false;
    if (old_path == "/" || new_path == "/" || old_path == new_path) {
        return kBadParameter;
    }
    FileInfo old_file;
    if (!LookUp(old_path, &old_file)) {
        LOG(INFO, "Rename not found: %s\n", old_path.c_str());
        return kNsNotFound;
    }

    std::vector<std::string> new_paths;
    if (!common::util::SplitPath(new_path, &new_paths) || new_paths.empty()) {
        LOG(INFO, "CreateFile split fail %s", new_path.c_str());
        return kBadParameter;
    }

    int64_t parent_id = kRootEntryid;
    for (uint32_t i = 0; i < new_paths.size() - 1; i++) {
        FileInfo path_file;
        if (!LookUp(parent_id, new_paths[i], &path_file)) {
            LOG(INFO, "Rename to %s which not exist", new_paths[i].c_str());
            return kNsNotFound;
        }
        if (!IsDir(path_file.type())) {
            LOG(INFO, "Rename %s to %s fail: %s is not a directory",
                old_path.c_str(), new_path.c_str(), new_paths[i].c_str());
            return kBadParameter;
        }
        parent_id = path_file.entry_id();
    }

    const std::string& dst_name = new_paths[new_paths.size() - 1];
    {
        /// dst_file maybe not exist, don't use it elsewhere.
        FileInfo dst_file;
        if (LookUp(parent_id, dst_name, &dst_file)) {
            if (IsDir(dst_file.type())) {
                LOG(INFO, "Rename %s to %s, target %o is a exist directory",
                    old_path.c_str(), new_path.c_str(), dst_file.type());
                return kTargetDirExists;
            }
            *need_unlink = true;
            remove_file->CopyFrom(dst_file);
            remove_file->set_name(dst_name);
        }
    }

    std::string old_key;
    EncodingStoreKey(old_file.parent_entry_id(), old_file.name(), &old_key);
    std::string new_key;
    EncodingStoreKey(parent_id, dst_name, &new_key);
    std::string value;
    old_file.clear_parent_entry_id();
    old_file.clear_name();
    old_file.SerializeToString(&value);

    // Write to persistent storage
    leveldb::WriteBatch batch;
    batch.Put(new_key, value);
    batch.Delete(old_key);

    EncodeLog(log, kSyncWrite, new_key, value);
    EncodeLog(log, kSyncDelete, old_key, "");

    leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
    if (s.ok()) {
        LOG(INFO, "Rename %s to %s[%s], replace: %d",
            old_path.c_str(), new_path.c_str(),
            common::DebugString(new_key).c_str(), *need_unlink);
        return kOK;
    } else {
        LOG(WARNING, "Rename write leveldb fail: %s %s", old_path.c_str(), s.ToString().c_str());
        return kUpdateError;
    }
}

StatusCode NameSpace::RemoveFile(const std::string& path, FileInfo* file_removed, NameServerLog* log) {
    StatusCode ret_status = kOK;
    if (LookUp(path, file_removed)) {
        // Only support file
        if ((file_removed->type() & (1<<9)) == 0) {
            if (path == "/" || path.empty()) {
                LOG(INFO, "root type= %d", file_removed->type());
            }
            std::string file_key;
            EncodingStoreKey(file_removed->parent_entry_id(), file_removed->name(), &file_key);
            if (DeleteFileInfo(file_key, log)) {
                LOG(INFO, "Unlink done: %s\n", path.c_str());
                ret_status = kOK;
            } else {
                LOG(WARNING, "Unlink write meta fail: %s\n", path.c_str());
                ret_status = kUpdateError;
            }
        } else {
            LOG(INFO, "Unlink not support directory: %s\n", path.c_str());
            ret_status = kBadParameter;
        }
    } else {
        LOG(INFO, "Unlink not found: %s\n", path.c_str());
        ret_status = kNsNotFound;
    }
    return ret_status;
}

StatusCode NameSpace::DiskUsage(const std::string& path, uint64_t* du_size) {
    if (!du_size) {
        return kOK;
    }
    *du_size = 0;
    FileInfo info;
    if (!LookUp(path, &info)) {
        LOG(INFO, "Du Directory or File, %s is not found.", path.c_str());
        return kNsNotFound;
    } else if (!IsDir(info.type())) {
        *du_size = info.size();
        return kOK;
    }
    return InternalComputeDiskUsage(info, du_size);
}

StatusCode NameSpace::InternalComputeDiskUsage(const FileInfo& info, uint64_t* du_size) {
    int64_t entry_id = info.entry_id();
    std::string key_start, key_end;
    EncodingStoreKey(entry_id, "", &key_start);
    EncodingStoreKey(entry_id + 1, "", &key_end);
    leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
    it->Seek(key_start);

    StatusCode ret_status = kOK;
    for (; it->Valid(); it->Next()) {
        leveldb::Slice key = it->key();
        if (key.compare(key_end) >= 0) {
            break;
        }
        std::string entry_name(key.data() + 8, key.size() - 8);
        FileInfo child_info;
        assert(child_info.ParseFromArray(it->value().data(), it->value().size()));
        if (IsDir(child_info.type())) {
            child_info.set_parent_entry_id(entry_id);
            ret_status = InternalComputeDiskUsage(child_info, du_size);
            if (ret_status != kOK) {
                break;
            }
        } else {
            //LOG(DEBUG, "Compute Disk Usage: E%ld, file %s, size %lu", entry_id, entry_name.c_str(), child_info.size());
            *du_size += child_info.size();
        }
    }
    delete it;
    return ret_status;
}

StatusCode NameSpace::DeleteDirectory(const std::string& path, bool recursive,
                               std::vector<FileInfo>* files_removed, NameServerLog* log) {
    files_removed->clear();
    FileInfo info;
    if (!LookUp(path, &info)) {
        LOG(INFO, "Delete Directory, %s is not found.", path.c_str());
        return kNsNotFound;
    } else if (!IsDir(info.type())) {
        LOG(INFO, "Delete Directory, %s %d is not a dir.", path.c_str(), info.type());
        return kBadParameter;
    }
    return InternalDeleteDirectory(info, recursive, files_removed, log);
}

StatusCode NameSpace::InternalDeleteDirectory(const FileInfo& dir_info,
                                       bool recursive,
                                       std::vector<FileInfo>* files_removed,
                                       NameServerLog* log) {
    int64_t entry_id = dir_info.entry_id();
    std::string key_start, key_end;
    EncodingStoreKey(entry_id, "", &key_start);
    EncodingStoreKey(entry_id + 1, "", &key_end);

    leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
    it->Seek(key_start);
    if (it->Valid() && it->key().compare(key_end) < 0 && recursive == false) {
        LOG(INFO, "Try to delete an unempty directory unrecursively: %s",
            dir_info.name().c_str());
        delete it;
        return kDirNotEmpty;
    }

    StatusCode ret_status = kOK;
    leveldb::WriteBatch batch;
    for (; it->Valid(); it->Next()) {
        leveldb::Slice key = it->key();
        if (key.compare(key_end) >= 0) {
            break;
        }
        std::string entry_name(key.data() + 8, key.size() - 8);
        FileInfo child_info;
        bool ret = child_info.ParseFromArray(it->value().data(), it->value().size());
        assert(ret);
        if (IsDir(child_info.type())) {
            child_info.set_parent_entry_id(entry_id);
            child_info.set_name(entry_name);
            LOG(INFO, "Recursive to path: %s", entry_name.c_str());
            ret_status = InternalDeleteDirectory(child_info, true, files_removed, log);
            if (ret_status != kOK) {
                break;
            }
        } else {
            EncodeLog(log, kSyncDelete, std::string(key.data(), key.size()), "");
            batch.Delete(key);
            child_info.set_parent_entry_id(entry_id);
            child_info.set_name(entry_name);
            LOG(DEBUG, "DeleteDirectory Remove push %s", entry_name.c_str());
            files_removed->push_back(child_info);
            LOG(INFO, "Unlink file: %s", entry_name.c_str());
        }
    }
    delete it;

    std::string store_key;
    EncodingStoreKey(dir_info.parent_entry_id(), dir_info.name(), &store_key);
    batch.Delete(store_key);
    EncodeLog(log, kSyncDelete, store_key, "");

    leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
    if (s.ok()) {
        LOG(INFO, "Delete directory done: %s[%s]",
            dir_info.name().c_str(), common::DebugString(store_key).c_str());
    } else {
        LOG(INFO, "Unlink dentry fail: %s\n", dir_info.name().c_str());
        LOG(FATAL, "Namespace write to storage fail!");
        ret_status = kUpdateError;
    }
    return ret_status;
}

bool NameSpace::RebuildBlockMap(boost::function<void (const FileInfo&)> callback) {
    int64_t block_num = 0;
    int64_t file_num = 0;
    std::set<int64_t> entry_id_set;
    entry_id_set.insert(root_path_.entry_id());
    leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
    for (it->Seek(std::string(7, '\0') + '\1'); it->Valid(); it->Next()) {
        FileInfo file_info;
        bool ret = file_info.ParseFromArray(it->value().data(), it->value().size());
        assert(ret);
        if (last_entry_id_ < file_info.entry_id()) {
            last_entry_id_ = file_info.entry_id();
        }
        if (!IsDir(file_info.type())) {
            //a file
            for (int i = 0; i < file_info.blocks_size(); i++) {
                if (file_info.blocks(i) >= next_block_id_) {
                    next_block_id_ = file_info.blocks(i) + 1;
                    block_id_upbound_ = next_block_id_;
                }
                ++block_num;
            }
            ++file_num;
            if (!callback.empty()) {
                callback(file_info);
            }
        } else {
            entry_id_set.insert(file_info.entry_id());
        }
    }
    LOG(INFO, "RebuildBlockMap done. %ld directories, %ld files, "
              "%lu blocks, last_entry_id= E%ld",
        entry_id_set.size(), file_num, block_num, last_entry_id_);
    if (FLAGS_check_orphan) {
        std::vector<std::pair<std::string, std::string> > orphan_entrys;
        for (it->Seek(std::string(7, '\0') + '\1'); it->Valid(); it->Next()) {
            FileInfo file_info;
            bool ret = file_info.ParseFromArray(it->value().data(), it->value().size());
            assert(ret);
            int64_t parent_entry_id = 0;
            std::string filename;
            DecodingStoreKey(it->key().ToString(), &parent_entry_id, &filename);
            if (entry_id_set.find(parent_entry_id) == entry_id_set.end()) {
                LOG(WARNING, "Orphan entry PE%ld E%ld %s",
                    parent_entry_id, file_info.entry_id(), filename.c_str());
                orphan_entrys.push_back(std::make_pair(it->key().ToString(),
                                                       it->value().ToString()));
            }
        }
        LOG(INFO, "Check orphan done, %lu entries", orphan_entrys.size());
    }
    delete it;
    return true;
}

std::string NameSpace::NormalizePath(const std::string& path) {
    // Is there a better implementation?
    std::string ret;
    if (path.empty() || path[0] != '/') {
        ret = "/";
    }
    bool slash = false;
    for (uint32_t i = 0; i < path.size(); i++) {
        if (path[i] == '/') {
            if (slash) continue;
            slash = true;
        } else {
            slash = false;
        }
        ret.push_back(path[i]);
    }
    if (ret.size() > 1U && ret[ret.size() - 1] == '/') {
        ret.resize(ret.size() - 1);
    }
    return ret;
}

void NameSpace::TailLog(const std::string& logstr) {
    NameServerLog log;
    if(!log.ParseFromString(logstr)) {
        LOG(FATAL, "Parse log fail: %s", common::DebugString(logstr).c_str());
    }
    for (int i = 0; i < log.entries_size(); i++) {
        const NsLogEntry& entry = log.entries(i);
        int type = entry.type();
        leveldb::Status s;
        if (type == kSyncWrite) {
            s = db_->Put(leveldb::WriteOptions(), entry.key(), entry.value());
        } else if (type == kSyncDelete) {
            s = db_->Delete(leveldb::WriteOptions(), entry.key());
        }
        if (!s.ok()) {
            LOG(FATAL, "TailLog failed");
        }
    }
}

uint32_t NameSpace::EncodeLog(NameServerLog* log, int32_t type,
                              const std::string& key, const std::string& value) {
    if (log == NULL) {
        return 0;
    }
    NsLogEntry* entry = log->add_entries();
    entry->set_type(type);
    entry->set_key(key);
    entry->set_value(value);
    return entry->ByteSize();
}
void NameSpace::UpdateBlockIdUpbound(NameServerLog* log) {
    std::string block_id_upbound_key(8, 0);
    block_id_upbound_key.append("block_id_upbound");
    std::string block_id_upbound_str;
    block_id_upbound_str.resize(8);
    assert(next_block_id_ == block_id_upbound_);
    block_id_upbound_ += FLAGS_block_id_allocation_size;
    *(reinterpret_cast<int64_t*>(&block_id_upbound_str[0])) = block_id_upbound_;
    leveldb::Status s = db_->Put(leveldb::WriteOptions(), block_id_upbound_key, block_id_upbound_str);
    if (!s.ok()) {
        LOG(FATAL, "Update block id upbound fail: %s", s.ToString().c_str());
    } else {
        LOG(INFO, "Update block id upbound to %ld", block_id_upbound_);
    }
    EncodeLog(log, kSyncWrite, block_id_upbound_key, block_id_upbound_str);
}
void NameSpace::InitBlockIdUpbound(NameServerLog* log) {
    std::string block_id_upbound_key(8, 0);
    block_id_upbound_key.append("block_id_upbound");
    std::string block_id_upbound_str;
    leveldb::Status s = db_->Get(leveldb::ReadOptions(), block_id_upbound_key, &block_id_upbound_str);
    if (s.IsNotFound()) {
        LOG(INFO, "Init block id upbound");
        UpdateBlockIdUpbound(log);
    } else if (s.ok()) {
        block_id_upbound_ = *(reinterpret_cast<int64_t*>(&block_id_upbound_str[0]));
        next_block_id_ = block_id_upbound_;
        LOG(INFO, "Load block id upbound: %ld", block_id_upbound_);
        UpdateBlockIdUpbound(log);
    } else {
        LOG(FATAL, "Load block id upbound failed: %s", s.ToString().c_str());
    }
}

int64_t NameSpace::GetNewBlockId(NameServerLog* log) {
    MutexLock lock(&mu_);
    if (next_block_id_ == block_id_upbound_) {
        UpdateBlockIdUpbound(log);
    }
    return next_block_id_++;
}

} // namespace bfs
} // namespace baidu
/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */

ext: cc


text:
/*!
@file
Defines `boost::hana::max`.

@copyright Louis Dionne 2013-2016
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_MAX_HPP
#define BOOST_HANA_MAX_HPP

#include <boost/hana/fwd/max.hpp>

#include <boost/hana/concept/orderable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/less.hpp>

BOOST_HANA_NAMESPACE_BEGIN
    //! @cond
    template <typename X, typename Y>
    constexpr decltype(auto) max_t::operator()(X&& x, Y&& y) const {
        using T = typename hana::tag_of<X>::type;
        using U = typename hana::tag_of<Y>::type;
        using Max = BOOST_HANA_DISPATCH_IF(decltype(max_impl<T, U>{}),
            hana::Orderable<T>::value &&
            hana::Orderable<U>::value
        );

    #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
        static_assert(hana::Orderable<T>::value,
        "hana::max(x, y) requires 'x' to be Orderable");

        static_assert(hana::Orderable<U>::value,
        "hana::max(x, y) requires 'y' to be Orderable");
    #endif

        return Max::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
    }
    //! @endcond

    template <typename T, typename U, bool condition>
    struct max_impl<T, U, when<condition>> : default_ {
        template <typename X, typename Y>
        static constexpr decltype(auto) apply(X&& x, Y&& y) {
            decltype(auto) cond = hana::less(x, y);
            return hana::if_(static_cast<decltype(cond)&&>(cond),
                static_cast<Y&&>(y),
                static_cast<X&&>(x)
            );
        }
    };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_MAX_HPP

ext: hpp

max_stars_repo_name: EuroLine/nheqminer


text: #include <boost/accumulators/statistics/weighted_density.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
///////////////////////////////////////////////////////////////////////////////
/// \file regex_constants.hpp
/// Contains definitions for the syntax_option_type, match_flag_type and
/// error_type enumerations.
//
//  Copyright 2004 Eric Niebler. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_XPRESSIVE_REGEX_CONSTANTS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_REGEX_CONSTANTS_HPP_EAN_10_04_2005

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif

#include <boost/mpl/identity.hpp>

#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
# define icase icase_
#endif

namespace boost { namespace xpressive { namespace regex_constants
{

/// Flags used to customize the regex syntax
///
enum syntax_option_type
{
    // these flags are required:

    ECMAScript  = 0,        ///< Specifies that the grammar recognized by the regular expression
                            ///< engine uses its normal semantics: that is the same as that given
                            ///< in the ECMA-262, ECMAScript Language Specification, Chapter 15
                            ///< part 10, RegExp (Regular Expression) Objects (FWD.1).
                            ///<
    icase       = 1 << 1,   ///< Specifies that matching of regular expressions against a character
                            ///< container sequence shall be performed without regard to case.
                            ///<
    nosubs      = 1 << 2,   ///< Specifies that when a regular expression is matched against a
                            ///< character container sequence, then no sub-expression matches are to
                            ///< be stored in the supplied match_results structure.
                            ///<
    optimize    = 1 << 3,   ///< Specifies that the regular expression engine should pay more
                            ///< attention to the speed with which regular expressions are matched,
                            ///< and less to the speed with which regular expression objects are
                            ///< constructed. Otherwise it has no detectable effect on the program
                            ///< output.
                            ///<
    collate     = 1 << 4,   ///< Specifies that character ranges of the form "[a-b]" should be
                            ///< locale sensitive.
                            ///<

    // These flags are optional. If the functionality is supported
    // then the flags shall take these names.

    //basic       = 1 << 5,   ///< Specifies that the grammar recognized by the regular expression
    //                        ///< engine is the same as that used by POSIX basic regular expressions
    //                        ///< in IEEE Std 1003.1-2001, Portable Operating System Interface
    //                        ///< (POSIX), Base Definitions and Headers, Section 9, Regular
    //                        ///< Expressions (FWD.1).
    //                        ///<
    //extended    = 1 << 6,   ///< Specifies that the grammar recognized by the regular expression
    //                        ///< engine is the same as that used by POSIX extended regular
    //                        ///< expressions in IEEE Std 1003.1-2001, Portable Operating System
    //                        ///< Interface (POSIX), Base Definitions and Headers, Section 9,
    //                        ///< Regular Expressions (FWD.1).
    //                        ///<
    //awk         = 1 << 7,   ///< Specifies that the grammar recognized by the regular expression
    //                        ///< engine is the same as that used by POSIX utility awk in IEEE Std
    //                        ///< 1003.1-2001, Portable Operating System Interface (POSIX), Shells
    //                        ///< and Utilities, Section 4, awk (FWD.1).
    //                        ///<
    //grep        = 1 << 8,   ///< Specifies that the grammar recognized by the regular expression
    //                        ///< engine is the same as that used by POSIX utility grep in IEEE Std
    //                        ///< 1003.1-2001, Portable Operating System Interface (POSIX),
    //                        ///< Shells and Utilities, Section 4, Utilities, grep (FWD.1).
    //                        ///<
    //egrep       = 1 << 9,   ///< Specifies that the grammar recognized by the regular expression
    //                        ///< engine is the same as that used by POSIX utility grep when given
    //                        ///< the -E option in IEEE Std 1003.1-2001, Portable Operating System
    //                        ///< Interface (POSIX), Shells and Utilities, Section 4, Utilities,
    //                        ///< grep (FWD.1).
    //                        ///<

    // these flags are specific to xpressive, and they help with perl compliance.

    single_line         = 1 << 10,  ///< Specifies that the ^ and \$ metacharacters DO NOT match at
                                    ///< internal line breaks. Note that this is the opposite of the
                                    ///< perl default. It is the inverse of perl's /m (multi-line)
                                    ///< modifier.
                                    ///<
    not_dot_null        = 1 << 11,  ///< Specifies that the . metacharacter does not match the null
                                    ///< character \\0.
                                    ///<
    not_dot_newline     = 1 << 12,  ///< Specifies that the . metacharacter does not match the
                                    ///< newline character \\n.
                                    ///<
    ignore_white_space  = 1 << 13   ///< Specifies that non-escaped white-space is not significant.
                                    ///<
};

/// Flags used to customize the behavior of the regex algorithms
///
enum match_flag_type
{
    match_default           = 0,        ///< Specifies that matching of regular expressions proceeds
                                        ///< without any modification of the normal rules used in
                                        ///< ECMA-262, ECMAScript Language Specification, Chapter 15
                                        ///< part 10, RegExp (Regular Expression) Objects (FWD.1)
                                        ///<
    match_not_bol           = 1 << 1,   ///< Specifies that the expression "^" should not be matched
                                        ///< against the sub-sequence [first,first).
                                        ///<
    match_not_eol           = 1 << 2,   ///< Specifies that the expression "\$" should not be
                                        ///< matched against the sub-sequence [last,last).
                                        ///<
    match_not_bow           = 1 << 3,   ///< Specifies that the expression "\\b" should not be
                                        ///< matched against the sub-sequence [first,first).
                                        ///<
    match_not_eow           = 1 << 4,   ///< Specifies that the expression "\\b" should not be
                                        ///< matched against the sub-sequence [last,last).
                                        ///<
    match_any               = 1 << 7,   ///< Specifies that if more than one match is possible then
                                        ///< any match is an acceptable result.
                                        ///<
    match_not_null          = 1 << 8,   ///< Specifies that the expression can not be matched
                                        ///< against an empty sequence.
                                        ///<
    match_continuous        = 1 << 10,  ///< Specifies that the expression must match a sub-sequence
                                        ///< that begins at first.
                                        ///<
    match_partial           = 1 << 11,  ///< Specifies that if no match can be found, then it is
                                        ///< acceptable to return a match [from, last) where
                                        ///< from!=last, if there exists some sequence of characters
                                        ///< [from,to) of which [from,last) is a prefix, and which
                                        ///< would result in a full match.
                                        ///<
    match_prev_avail        = 1 << 12,  ///< Specifies that --first is a valid iterator position,
                                        ///< when this flag is set then the flags match_not_bol
                                        ///< and match_not_bow are ignored by the regular expression
                                        ///< algorithms (RE.7) and iterators (RE.8).
                                        ///<
    format_default          = 0,        ///< Specifies that when a regular expression match is to be
                                        ///< replaced by a new string, that the new string is
                                        ///< constructed using the rules used by the ECMAScript
                                        ///< replace function in ECMA-262, ECMAScript Language
                                        ///< Specification, Chapter 15 part 5.4.11
                                        ///< String.prototype.replace. (FWD.1). In addition during
                                        ///< search and replace operations then all non-overlapping
                                        ///< occurrences of the regular expression are located and
                                        ///< replaced, and sections of the input that did not match
                                        ///< the expression, are copied unchanged to the output
                                        ///< string.
                                        ///<
    //format_sed              = 1 << 13,  ///< Specifies that when a regular expression match is to be
    //                                    ///< replaced by a new string, that the new string is
    //                                    ///< constructed using the rules used by the Unix sed
    //                                    ///< utility in IEEE Std 1003.1-2001, Portable Operating
    //                                    ///< SystemInterface (POSIX), Shells and Utilities.
    //                                    ///<
    //format_perl             = 1 << 14,  ///< Specifies that when a regular expression match is to be
    //                                    ///< replaced by a new string, that the new string is
    //                                    ///< constructed using an implementation defined superset
    //                                    ///< of the rules used by the ECMAScript replace function in
    //                                    ///< ECMA-262, ECMAScript Language Specification, Chapter 15
    //                                    ///< part 5.4.11 String.prototype.replace (FWD.1).
    //                                    ///<
    format_no_copy          = 1 << 15,  ///< When specified during a search and replace operation,
                                        ///< then sections of the character container sequence being
                                        ///< searched that do match the regular expression, are not
                                        ///< copied to the output string.
                                        ///<
    format_first_only       = 1 << 16,  ///< When specified during a search and replace operation,
                                        ///< then only the first occurrence of the regular
                                        ///< expression is replaced.
                                        ///<
    format_literal          = 1 << 17   ///< Treat the format string as a literal.
                                        ///<
};

/// Error codes used by the regex_error type
///
enum error_type
{
    error_collate,              ///< The expression contained an invalid collating element name.
                                ///<
    error_ctype,                ///< The expression contained an invalid character class name.
                                ///<
    error_escape,               ///< The expression contained an invalid escaped character,
                                ///< or a trailing escape.
                                ///<
    error_subreg,               ///< The expression contained an invalid back-reference.
                                ///<
    error_brack,                ///< The expression contained mismatched [ and ].
                                ///<
    error_paren,                ///< The expression contained mismatched (and).
                                ///<
    error_brace,                ///< The expression contained mismatched { and }
                                ///<
    error_badbrace,             ///< The expression contained an invalid range in a {} expression.
                                ///<
    error_range,                ///< The expression contained an invalid character range, for
                                ///< example [b-a].
                                ///<
    error_space,                ///< There was insufficient memory to convert the expression into a
                                ///< finite state machine.
                                ///<
    error_badrepeat,            ///< One of *?+{ was not preceded by a valid regular expression.
                                ///<
    error_complexity,           ///< The complexity of an attempted match against a regular
                                ///< expression exceeded a pre-set level.
                                ///<
    error_stack,                ///< There was insufficient memory to determine whether the regular
                                ///< expression could match the specified character sequence.
                                ///<
    error_badref,               ///< An nested regex is uninitialized.
                                ///<
    error_badlookbehind,        ///< An attempt to create a variable-width look-behind assertion
                                ///< was detected.
                                ///<
    error_internal              ///< An internal error has occured.
                                ///<
};

/// INTERNAL ONLY
inline syntax_option_type operator &(syntax_option_type b1, syntax_option_type b2)
{
    return static_cast<syntax_option_type>(
        static_cast<int>(b1) & static_cast<int>(b2));
}

/// INTERNAL ONLY
inline syntax_option_type operator |(syntax_option_type b1, syntax_option_type b2)
{
    return static_cast<syntax_option_type>(static_cast<int>(b1) | static_cast<int>(b2));
}

/// INTERNAL ONLY
inline syntax_option_type operator ^(syntax_option_type b1, syntax_option_type b2)
{
    return static_cast<syntax_option_type>(static_cast<int>(b1) ^ static_cast<int>(b2));
}

/// INTERNAL ONLY
inline syntax_option_type operator ~(syntax_option_type b)
{
    return static_cast<syntax_option_type>(~static_cast<int>(b));
}

/// INTERNAL ONLY
inline match_flag_type operator &(match_flag_type b1, match_flag_type b2)
{
    return static_cast<match_flag_type>(static_cast<int>(b1) & static_cast<int>(b2));
}

/// INTERNAL ONLY
inline match_flag_type operator |(match_flag_type b1, match_flag_type b2)
{
    return static_cast<match_flag_type>(static_cast<int>(b1) | static_cast<int>(b2));
}

/// INTERNAL ONLY
inline match_flag_type operator ^(match_flag_type b1, match_flag_type b2)
{
    return static_cast<match_flag_type>(static_cast<int>(b1) ^ static_cast<int>(b2));
}

/// INTERNAL ONLY
inline match_flag_type operator ~(match_flag_type b)
{
    return static_cast<match_flag_type>(~static_cast<int>(b));
}

}}} // namespace boost::xpressive::regex_constants

#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
# undef icase
#endif

#endif


text: #include <boost/fusion/iterator/next.hpp>


text:
#ifndef KA_SHA1_HPP
#define KA_SHA1_HPP
#pragma once
#include <array>
#include <cstdint>
#include <type_traits>
#include <openssl/sha.h>
#include <boost/uuid/sha1.hpp>
#include "scoped.hpp"
#include "typetraits.hpp"

/// @file Contains sha1 digest functions.
///
/// The implementation relies on openssl.
///
/// An alternative is `boost::uuids::detail::sha1` but:
/// 1) it is in a `detail` namespace, so not officially supported
/// 2) the produced digests are different from the one of tools such as
///    `openssl sha1` and `sha1sum` (!).
///    This is apparently because of a wrong handling of endianness.

namespace ka {
  /// The result of a sha1 computation is an array of 20 bytes.
  using sha1_digest_t = std::array<uint8_t, 20>;

  namespace detail {
    // With pointers, we use the single-call update.
    //
    // Precondition: boundedRange(b, e) && s has been initialized
    //
    // I == T*, with T having the size of one byte (e.g. int8_t, uint8_t,
    // unsigned char on some platforms, etc.)
    template<typename I>
    int sha1_update(SHA_CTX& s, I b, I e, std::true_type /* is_pointer */) {
      return SHA1_Update(&s, b, e - b);
    }

    // With non-pointer iterators, we update byte by byte.
    //
    // Precondition: boundedRange(b, e) && s has been initialized
    //
    // InputIterator<T> I, with T having the size of one byte
    template<typename I>
    int sha1_update(SHA_CTX& s, I b, I e, std::false_type /* is_pointer */) {
      int res = 1;
      while (b != e) {
        auto const c = *b;
        res = SHA1_Update(&s, &c, 1u);
        if (res == 0) {
          return res;
        }
        ++b;
      }
      return res;
    }
  } // namespace detail

  /// Computes the sha1 digest of the given bytes.
  ///
  /// Note: Passing pointers instead of non-pointer iterators (even random access ones)
  ///   will typically be faster, due to the underlying C api.
  ///
  /// Precondition: boundedRange(b, e)
  ///
  /// InputIterator<T> I, with T having the size of one byte
  template<typename I>
  sha1_digest_t sha1(I b, I e) {
    static_assert(sizeof(Decay<decltype(*b)>) == 1,
      "sha1: element size is different than 1.");
    SHA_CTX x;
    if (!SHA1_Init(&x)) {
      throw std::runtime_error("Can't initialize the sha1 context. "
                               "data=\"" + std::string(b, e) + "\"");
    }
    bool release = false;
    auto _ = scoped([&]() {
      if (!release) {
        // `SHA1_Final` both computes and frees the context.
        // Here we just want to free, but there's no other way...
        SHA1_Final(sha1_digest_t{{0}}.data(), &x);
      }
    });
    if (!detail::sha1_update(x, b, e, std::is_pointer<I>{})) {
      throw std::runtime_error("Can't update sha1 on \"" + std::string(b, e) + "\"");
    }
    sha1_digest_t d;
    release = true;
    if (!SHA1_Final(d.data(), &x)) {
      throw std::runtime_error("Can't compute sha1 on \"" + std::string(b, e) + "\"");
    }
    return d;
  }

  /// Computes the sha1 digest of the given bytes.
  ///
  /// Warning: This function operates on binary data. If you pass a string literal,
  /// it will be processed as a normal array. This means that the final '\0' will
  /// be processed.
  ///
  /// Thus beware that:
  /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /// assert(sha1("youpi") != sha1(std::string{"youpi"}));
  /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ///
  /// Linearizable<T> L, with T having the size of one byte
  template<typename L>
  sha1_digest_t sha1(L const& l) {
    using std::begin;
    using std::end;
    return sha1(begin(l), end(l));
  }
} // namespace ka

#endif // KA_SHA1_HPP

max_stars_repo_name: yumilceh/libqi

max_issues_repo_name: yumilceh/libqi

max_forks_repo_name: yumilceh/libqi


text:
//
// Copyright (c) 2008, 2009 Boris Schaeling <boris@highscore.de>
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include "dir_monitor.hpp"
#include "directory.hpp"

boost::asio::io_service io_service;

void create_file_handler(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    boost::filesystem::path fullpath = boost::filesystem::canonical(TEST_DIR1);
    fullpath /= TEST_FILE1;

    BOOST_CHECK_EQUAL(ec, boost::system::error_code());
    BOOST_CHECK_EQUAL(ev.path, fullpath);
    BOOST_CHECK_EQUAL(ev.type, boost::asio::dir_monitor_event::added);
}

BOOST_AUTO_TEST_CASE(create_file)
{
    directory dir(TEST_DIR1);

    boost::asio::dir_monitor dm(io_service);
    dm.add_directory(TEST_DIR1);

    dir.create_file(TEST_FILE1);

    dm.async_monitor(create_file_handler);
    io_service.run();
    io_service.reset();
}

void rename_file_handler_old(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    boost::filesystem::path fullpath = boost::filesystem::canonical(TEST_DIR1);
    fullpath /= TEST_FILE1;

    BOOST_CHECK_EQUAL(ec, boost::system::error_code());
    BOOST_CHECK_EQUAL(ev.path, fullpath);
    BOOST_CHECK_EQUAL(ev.type, boost::asio::dir_monitor_event::renamed_old_name);
}

void rename_file_handler_new(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    boost::filesystem::path fullpath = boost::filesystem::canonical(TEST_DIR1);
    fullpath /= TEST_FILE2;

    BOOST_CHECK_EQUAL(ec, boost::system::error_code());
    BOOST_CHECK_EQUAL(ev.path, fullpath);
    BOOST_CHECK_EQUAL(ev.type, boost::asio::dir_monitor_event::renamed_new_name);
}

void modify_file_handler(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    boost::filesystem::path fullpath = boost::filesystem::canonical(TEST_DIR1);
    fullpath /= TEST_FILE2;

    BOOST_CHECK_EQUAL(ec, boost::system::error_code());
    BOOST_CHECK_EQUAL(ev.path, fullpath);
    BOOST_CHECK_EQUAL(ev.type, boost::asio::dir_monitor_event::modified);
}

BOOST_AUTO_TEST_CASE(rename_file)
{
    directory dir(TEST_DIR1);
    dir.create_file(TEST_FILE1);

    boost::asio::dir_monitor dm(io_service);
    dm.add_directory(TEST_DIR1);

    dir.rename_file(TEST_FILE1, TEST_FILE2);

    dm.async_monitor(rename_file_handler_old);
    io_service.run();
    io_service.reset();

    dm.async_monitor(rename_file_handler_new);
    io_service.run();
    io_service.reset();

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
    dm.async_monitor(modify_file_handler);
    io_service.run();
    io_service.reset();
#endif
}

void remove_file_handler(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    boost::filesystem::path fullpath = boost::filesystem::canonical(TEST_DIR1);
    fullpath /= TEST_FILE1;

    BOOST_CHECK_EQUAL(ec, boost::system::error_code());
    BOOST_CHECK_EQUAL(ev.path, fullpath);
    BOOST_CHECK_EQUAL(ev.type, boost::asio::dir_monitor_event::removed);
}

BOOST_AUTO_TEST_CASE(remove_file)
{
    directory dir(TEST_DIR1);
    dir.create_file(TEST_FILE1);

    boost::asio::dir_monitor dm(io_service);
    dm.add_directory(TEST_DIR1);

    dir.remove_file(TEST_FILE1);

    dm.async_monitor(remove_file_handler);
    io_service.run();
    io_service.reset();
}

BOOST_AUTO_TEST_CASE(multiple_events)
{
    directory dir(TEST_DIR1);

    boost::asio::dir_monitor dm(io_service);
    dm.add_directory(TEST_DIR1);

    dir.create_file(TEST_FILE1);
    dir.rename_file(TEST_FILE1, TEST_FILE2);

    dm.async_monitor(create_file_handler);
    io_service.run();
    io_service.reset();

    dm.async_monitor(rename_file_handler_old);
    io_service.run();
    io_service.reset();

    dm.async_monitor(rename_file_handler_new);
    io_service.run();
    io_service.reset();

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
    dm.async_monitor(modify_file_handler);
    io_service.run();
    io_service.reset();
#endif
}

void aborted_async_call_handler(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    BOOST_CHECK_EQUAL(ec, boost::asio::error::operation_aborted);
}

BOOST_AUTO_TEST_CASE(aborted_async_call)
{
    directory dir(TEST_DIR1);

    {
        boost::asio::dir_monitor dm(io_service);
        dm.add_directory(TEST_DIR1);

        dm.async_monitor(aborted_async_call_handler);
    }

    io_service.run();
    io_service.reset();
}

void blocked_async_call_handler_with_local_ioservice(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    BOOST_CHECK_EQUAL(ec, boost::asio::error::operation_aborted);
}

BOOST_AUTO_TEST_CASE(blocked_async_call)
{
    directory dir(TEST_DIR1);
    boost::thread t;

    {
        boost::asio::io_service io_service;

        boost::asio::dir_monitor dm(io_service);
        dm.add_directory(TEST_DIR1);

        dm.async_monitor(blocked_async_call_handler_with_local_ioservice);

        // run() is invoked on another thread to make async_monitor() call a blocking function.
        // When dm and io_service go out of scope they should be destroyed properly without
        // a thread being blocked.
        t = boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(io_service)));
        boost::system_time time = boost::get_system_time();
        time += boost::posix_time::time_duration(0, 0, 1);
        boost::thread::sleep(time);
    }

    t.join();
    io_service.reset();
}

void unregister_directory_handler(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    BOOST_CHECK_EQUAL(ec, boost::asio::error::operation_aborted);
}

BOOST_AUTO_TEST_CASE(unregister_directory)
{
    directory dir(TEST_DIR1);
    boost::thread t;

    {
        boost::asio::dir_monitor dm(io_service);
        dm.add_directory(TEST_DIR1);
        dm.remove_directory(TEST_DIR1);

        dir.create_file(TEST_FILE1);

        dm.async_monitor(unregister_directory_handler);

        // run() is invoked on another thread to make this test case return. Without using
        // another thread run() would block as the file was created after remove_directory()
        // had been called.
        t = boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(io_service)));
        boost::system_time time = boost::get_system_time();
        time += boost::posix_time::time_duration(0, 0, 1);
        boost::thread::sleep(time);
    }

    t.join();
    io_service.reset();
}

void two_dir_monitors_handler(const boost::system::error_code &ec, const boost::asio::dir_monitor_event &ev)
{
    BOOST_CHECK_EQUAL(ec, boost::asio::error::operation_aborted);
}

BOOST_AUTO_TEST_CASE(two_dir_monitors)
{
    directory dir1(TEST_DIR1);
    directory dir2(TEST_DIR2);
    boost::thread t;

    {
        boost::asio::dir_monitor dm1(io_service);
        dm1.add_directory(TEST_DIR1);

        boost::asio::dir_monitor dm2(io_service);
        dm2.add_directory(TEST_DIR2);

        dir2.create_file(TEST_FILE1);

        dm1.async_monitor(two_dir_monitors_handler);

        // run() is invoked on another thread to make this test case return. Without using
        // another thread run() would block as the directory the file was created in is
        // monitored by dm2 while async_monitor() was called for dm1.
        t = boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(io_service)));
        boost::system_time time = boost::get_system_time();
        time += boost::posix_time::time_duration(0, 0, 1);
        boost::thread::sleep(time);
    }

    t.join();
    io_service.reset();
}

ext: cpp


text:
#include <boost/algorithm/string.hpp>
#include <stack>
#include <unordered_map>

#include "Layout.hpp"

#define PARAGRAPH_BREAK_PADDING 14
#define LEADING 2

namespace WordSizes
{
    std::unordered_map<std::wstring, int> word_lengths;
    std::unordered_map<std::wstring, int> word_heights;
}

int Layout::get_word_length(const std::wstring& word)
{
    int word_length;

    if (WordSizes::word_lengths.find(word) == WordSizes::word_lengths.end())
    {
        text.setString(word);
        word_length = text.getLocalBounds().width;
        WordSizes::word_lengths.insert({word, word_length});
    }

    else
        word_length = WordSizes::word_lengths.at(word);

    return word_length;
}

int Layout::get_word_height(const std::wstring& word)
{
    int word_height;

    if (WordSizes::word_heights.find(word) == WordSizes::word_heights.end())
    {
        text.setString(word);
        word_height = text.getLocalBounds().height;
        WordSizes::word_heights.insert({word, word_height});
    }

    else
        word_height = WordSizes::word_heights.at(word);

    return word_height;
}

Layout::Layout()
{
    cursor_x = 0;
    cursor_y = 0;
    boxes = {};

    is_font_set = font.loadFromFile("/usr/share/fonts/TTF/DejaVuSerif.ttf");

    text.setCharacterSize(14);
    text.setFont(font);

    is_last_box_finalized = false;

    if (WordSizes::word_lengths.count(L" ") == 0)
    {
        text.setString(" ");
        WordSizes::word_lengths.insert({L" ", text.getLocalBounds().width});
        WordSizes::word_heights.insert({L" ", text.getLocalBounds().height});
        text.setString("");
    }

}

void push_remaining_children(const std::vector<std::shared_ptr<HTMLElement>> &c,
        std::stack<std::vector<std::shared_ptr<HTMLElement>>> &r)
{
    if (c.size() <= 1)
        r.push({});

    else
    {
        std::vector<std::shared_ptr<HTMLElement>>
            rest_children(c.begin() + 1, c.end());

        r.push(rest_children);
    }
}

void Layout::construct_from_document(const Document &doc)
{
    boxes = {};
    cursor_x = 0;
    cursor_y = 0;

    document = doc;

    auto node = document.get_elements().front();

    std::stack<std::vector<std::shared_ptr<HTMLElement>>> remaining_children;
    auto root_children = node->get_children();

    push_remaining_children(node->get_children(), remaining_children);

    while (true)
    {
        if (node->is_text_node())
            add_string(node->get_text());

        else if (node->is_paragraph_node())
        {
            if (boxes.size() > 0)
            {
                is_last_box_finalized = true;
                cursor_y += PARAGRAPH_BREAK_PADDING;
            }
        }

        if (node->get_children().size() > 0)
        {
            node = node->get_children().front();
            push_remaining_children(node->get_children(), remaining_children);
        }

        else
        {
            while (remaining_children.top().size() == 0)
            {
                remaining_children.pop();

                if (remaining_children.size() == 0)
                    break;
            }

            if (remaining_children.size() == 0)
                break;

            auto current_children = remaining_children.top();
            remaining_children.pop();

            node = current_children.front();
            push_remaining_children(current_children, remaining_children);
        }
    }
}

void Layout::set_width(const int &new_width)
{
    width = new_width;
}

void Layout::add_string(const std::wstring &string)
{
    std::vector<std::wstring> words;
    boost::split(words, string, boost::is_any_of(L" "));

    int space_length = WordSizes::word_lengths.at(L" ");
    int space_height = WordSizes::word_heights.at(L" ");
    int box_height = space_height;
    int box_length = 0;
    int word_length, word_height;

    Box current_box;
    if (boxes.size() > 0)
    {
        if (!is_last_box_finalized)
        {
            current_box = boxes.at(boxes.size() - 1);
            boxes.pop_back();
            box_length = current_box.get_width();
        }

        else
            current_box.set_coordinates({cursor_x, cursor_y});
    }

    else
    {
        current_box.set_coordinates({cursor_x, cursor_y});
        is_last_box_finalized = false;
    }

    std::wstring current_string = current_box.get_box_string();
    std::wstring old_string = current_string;

    std::vector<int> coordinates = current_box.get_coordinates();

    for (const auto& word : words)
    {
        current_string += word;

        word_length = get_word_length(word);
        word_height = get_word_height(word);

        if (cursor_x + box_length + space_length + word_length < width)
        {
            box_length += space_length + word_length;
            if (word_height > box_height)
                box_height = word_height;

            current_box.set_box_string(current_string);
        }

        else
        {
            current_box.set_box_string(old_string);
            current_box.set_width(box_length);
            current_box.set_height(box_height);
            boxes.push_back(current_box);
            is_last_box_finalized = true;
            cursor_y += box_height + LEADING;

            current_box = Box();

            box_length = word_length;
            box_height = word_height;

            current_string = word;
            old_string = current_string;
            current_box.set_box_string(current_string);
            current_box.set_coordinates({cursor_x, cursor_y});
        }

        current_box.set_width(box_length);
        current_box.set_height(box_height);

        old_string = current_string;
        current_string += L" ";
    }

    // If we hit the last word, then we added an extra space to the length
    if (!is_last_box_finalized)
    {
        box_length -= space_length;
        current_box.set_width(box_length);
    }

    boxes.push_back(current_box);
    cursor_y += box_height;
}

std::vector<Box> Layout::get_boxes() const
{
    return boxes;
}

int Layout::get_max_width()
{
    int width = 0;

    for (auto box : boxes)
    {
        if (box.get_width() > width)
            width = box.get_width();
    }

    return width;
}

int Layout::get_max_height()
{
    int height = 0;

    for (auto box : boxes)
    {
        if (box.get_coordinates().at(1) + box.get_height() > height)
            height = box.get_coordinates().at(1) + box.get_height();
    }

    return height;
}

void Layout::update()
{
    construct_from_document(document);

    auto center = view.getCenter();
    auto size = view.getSize();
    sf::FloatRect view_bounds(center.x - (size.x / 2), center.y - (size.y / 2),
            size.x, size.y);

    for (auto& box : boxes)
    {
        auto coordinates = box.get_coordinates();
        box.set_visible(view_bounds.intersects(sf::FloatRect(coordinates.at(0),
                        coordinates.at(1), box.get_width(), box.get_height())));
    }
}

void Layout::set_view(const sf::View &new_view)
{
    view = new_view;
}

max_stars_repo_name: windlessStorm/WebWhir

max_issues_repo_name: windlessStorm/WebWhir

max_forks_repo_name: windlessStorm/WebWhir


text:
/* Copyright (c) 2018, Skolkovo Institute of Science and Technology (Skoltech)
 * All rights reserved.
 *
 * See LICENSE file in the root of the mrob library.
 *
 *
 * plane_factor.cpp
 *
 *  Created on: Aug 16, 2019
 *      Author: Gonzalo Ferrer
 *              g.ferrer@skoltech.ru
 *              Mobile Robotics Lab.
 */

#include "mrob/plane_factor.hpp"

#include <iostream>
#include <Eigen/Eigenvalues>
#include "mrob/SE3.hpp"

using namespace mrob;

PlaneFactor::PlaneFactor(const Mat4 &S, std::shared_ptr<Node> &nodeOrigin):
        Factor(0,0), //Dimension zero since this is a non-parametric factor. Also we don't known how many nodes will connect, so we set the second param to 0 (not-used)
        planeEstimation_(Mat41::Zero()),
        planeError_(0.0)
{
    planeNodes_.push_back(nodeOrigin);
    S_.emplace(nodeOrigin->get_id(), S);//TODO ids make sense? not really
}

void PlaneFactor::add_observation(const Mat4& S, std::shared_ptr<Node> &newNode)
{
    //neighbourNodes_ contain only those node to be optimized
    planeNodes_.push_back(newNode);
    S_.emplace(newNode->get_id(), S);
}

double PlaneFactor::estimate_plane()
{
    calculate_all_matrices_Q();
    accumulatedQ_ = Mat4::Zero();
    for (const auto &Qi: Q_)
    {
        accumulatedQ_ += Qi.second;
        //std::cout << Qi << std::endl;
    }

    // Only needs Lower View from Q (https://eigen.tuxfamily.org/dox/classEigen_1_1SelfAdjointEigenSolver.html)
    Eigen::SelfAdjointEigenSolver<Mat4> es(accumulatedQ_);
    planeEstimation_ = es.eigenvectors().col(0);
    //std::cout << es.eigenvectors() << "\n and solution \n" << planeEstimation_ <<  std::endl;
    //std::cout << "plane estimation error: " << es.eigenvalues() <<  std::endl;
    planeError_ = es.eigenvalues()(0);

    return planeError_;
}

void PlaneFactor::calculate_all_matrices_Q()
{
    Q_.clear();
    for (auto &element : S_)
    {
        // Find the corresponding transformation, on this pair<id, S>
        uint_t nodeId = element.first;
        SE3 T;
        // Use the corresponding matrix S
        Mat4 Q;
        Q.noalias() =  T.T() * element.second * T.T().transpose();
        Q_.emplace(nodeId, Q);
    }
}

Mat61 PlaneFactor::calculate_jacobian(uint_t nodeId)
{
    if (S_.count(nodeId) == 0) return Mat61::Zero();
    Mat61 jacobian;
    // calculate dQ/dxi for the submatrix S
    // XXX for now keep vectors S and Q and create a separate vector/map for adding optimization nodes or do not include others???
    Mat4 dQ, Q;// = matrixQ_[];

    // dQ / d xi(0) = [0
    //               -q3
    //                q2
    //                 0]
    dQ.setZero();
    dQ.row(1) << -Q.row(2);
    dQ.row(2) <<  Q.row(1);
    dQ += dQ.transpose().eval();
    jacobian(0) = planeEstimation_.dot(dQ*planeEstimation_);

    // dQ / d xi(1) = [q3
    //                 0
    //                -q1
    //                 0]
    dQ.setZero();
    dQ.row(0) <<  Q.row(2);
    dQ.row(2) << -Q.row(0);
    dQ += dQ.transpose().eval();
    jacobian(1) = planeEstimation_.dot(dQ*planeEstimation_);

    // dQ / d xi(2) = [-q2
    //                 q1
    //                 0
    //                 0]
    dQ.setZero();
    dQ.row(0) << -Q.row(1);
    dQ.row(1) <<  Q.row(0);
    dQ += dQ.transpose().eval();
    jacobian(2) = planeEstimation_.dot(dQ*planeEstimation_);

    // dQ / d xi(3) = [q4
    //                 0
    //                 0
    //                 0]
    dQ.setZero();
    dQ.row(0) << Q.row(3);
    dQ += dQ.transpose().eval();
    jacobian(3) = planeEstimation_.dot(dQ*planeEstimation_);

    // dQ / d xi(4) = [0
    //                 q4
    //                 0
    //                 0]
    dQ.setZero();
    dQ.row(1) << Q.row(3);
    dQ += dQ.transpose().eval();
    jacobian(4) = planeEstimation_.dot(dQ*planeEstimation_);

    // dQ / d xi(5) = [0
    //                 0
    //                 q4
    //                 0]
    dQ.setZero();
    dQ.row(2) << Q.row(3);
    dQ += dQ.transpose().eval();
    jacobian(5) = planeEstimation_.dot(dQ*planeEstimation_);

    return jacobian;
}

void PlaneFactor::print() const
{
    std::cout << "Plane Eigen Factor" <<std::endl;
}

max_stars_repo_name: anastasiia-kornilova/mrob

max_issues_repo_name: anastasiia-kornilova/mrob

max_forks_repo_name: anastasiia-kornilova/mrob


text:
#include "ReflectionCoefficientsLocBulk.h"
#include <armadillo>
#include <utility>
// direct constructor
ReflectionCoefficientsLocBulk::ReflectionCoefficientsLocBulk(
    std::shared_ptr<Permittivity> permittivity)
    : permittivity(std::move(permittivity)) {}

// constructor from .json file
ReflectionCoefficientsLocBulk::ReflectionCoefficientsLocBulk(
    const std::string &input_file) {
  // set permittivity
  this->permittivity = PermittivityFactory::create(input_file);
}

// calculate the p-polarized reflection coefficient
void ReflectionCoefficientsLocBulk::calculate(double omega,
                                              std::complex<double> kappa,
                                              std::complex<double> &r_p,
                                              std::complex<double> &r_s) const {
  // absolute value of omega. r_p is always calculated for positive omega and if
  // needed complex conjugated after the calculation
  double omega_abs = std::abs(omega);
  std::complex<double> eps = this->permittivity->calculate(omega_abs);
  std::complex<double> eps_omega = this->permittivity->calculate_times_omega(omega_abs);

  // kapppa as well as kappa_epsilon are defined to have either a purely
  // positive real part or purely negatively imaginary part
  std::complex<double> kappa_epsilon =
      sqrt(kappa * kappa - (eps - 1.) * omega_abs * omega_abs);
  kappa_epsilon = std::complex<double>(std::abs(kappa_epsilon.real()),
                                       -std::abs(kappa_epsilon.imag()));
  // Defining the reflection coefficients in transverse magnetice polarization
  // (p) and in transverse electric polarization (s)
  r_p = (kappa * eps_omega - kappa_epsilon*omega_abs) / (kappa * eps_omega + kappa_epsilon*omega_abs);
  r_s = (kappa - kappa_epsilon) / (kappa + kappa_epsilon);
  // Imposing crossing relation
  if (omega < 0.) {
    r_p = conj(r_p);
    r_s = conj(r_s);
  }
}

void ReflectionCoefficientsLocBulk::print_info(std::ostream &stream) const {
  stream << "# ReflectionCoefficientsLocBulk\n#\n";
  permittivity->print_info(stream);
}

max_stars_repo_name: QuaCaTeam/quaca

max_issues_repo_name: myoelmy/quaca

max_forks_repo_name: myoelmy/quaca


text:
/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

#include <boost/algorithm/string.hpp>
#include <ored/configuration/fxvolcurveconfig.hpp>
#include <ored/utilities/parsers.hpp>
#include <ored/utilities/to_string.hpp>
#include <ql/errors.hpp>

using ore::data::XMLUtils;

namespace ore {
namespace data {

FXVolatilityCurveConfig::FXVolatilityCurveConfig(const string& curveID, const string& curveDescription,
                                                 const Dimension& dimension, const vector<Period>& expiries,
                                                 const string& fxSpotID, const string& fxForeignCurveID,
                                                 const string& fxDomesticCurveID, const DayCounter& dayCounter,
                                                 const Calendar& calendar)

    : CurveConfig(curveID, curveDescription), dimension_(dimension), expiries_(expiries), dayCounter_(dayCounter),
      calendar_(calendar), fxSpotID_(fxSpotID), fxForeignYieldCurveID_(fxForeignCurveID),
      fxDomesticYieldCurveID_(fxDomesticCurveID) {}

const vector<string>& FXVolatilityCurveConfig::quotes() {
    if (quotes_.size() == 0) {
        vector<string> tokens;
        boost::split(tokens, fxSpotID(), boost::is_any_of("/"));
        string base = "FX_OPTION/RATE_LNVOL/" + tokens[1] + "/" + tokens[2] + "/";
        for (auto e : expiries_) {
            quotes_.push_back(base + to_string(e) + "/ATM");
            if (dimension_ == Dimension::Smile) {
                quotes_.push_back(base + to_string(e) + "/25RR");
                quotes_.push_back(base + to_string(e) + "/25BF");
            }
        }
    }
    return quotes_;
}

void FXVolatilityCurveConfig::fromXML(XMLNode* node) {
    XMLUtils::checkNode(node, "FXVolatility");

    curveID_ = XMLUtils::getChildValue(node, "CurveId", true);
    curveDescription_ = XMLUtils::getChildValue(node, "CurveDescription", true);
    string dim = XMLUtils::getChildValue(node, "Dimension", true);
    string cal = XMLUtils::getChildValue(node, "Calendar");
    if (cal == "")
        cal = "TARGET";
    calendar_ = parseCalendar(cal);

    string dc = XMLUtils::getChildValue(node, "DayCounter");
    if (dc == "")
        dc = "A365";
    dayCounter_ = parseDayCounter(dc);

    if (dim == "ATM") {
        dimension_ = Dimension::ATM;
    } else if (dim == "Smile") {
        dimension_ = Dimension::Smile;
    } else {
        QL_FAIL("Dimension " << dim << " not supported yet");
    }
    expiries_ = XMLUtils::getChildrenValuesAsPeriods(node, "Expiries", true);
    fxSpotID_ = XMLUtils::getChildValue(node, "FXSpotID", true);

    if (dimension_ == Dimension::Smile) {
        fxForeignYieldCurveID_ = XMLUtils::getChildValue(node, "FXForeignCurveID", true);
        fxDomesticYieldCurveID_ = XMLUtils::getChildValue(node, "FXDomesticCurveID", true);
    }
}

XMLNode* FXVolatilityCurveConfig::toXML(XMLDocument& doc) {
    XMLNode* node = doc.allocNode("FXVolatility");

    XMLUtils::addChild(doc, node, "CurveId", curveID_);
    XMLUtils::addChild(doc, node, "CurveDescription", curveDescription_);
    if (dimension_ == Dimension::ATM) {
        XMLUtils::addChild(doc, node, "Dimension", "ATM");
    } else if (dimension_ == Dimension::Smile) {
        XMLUtils::addChild(doc, node, "Dimension", "Smile");
    } else {
        QL_FAIL("Unkown Dimension in FXVolatilityCurveConfig::toXML()");
    }
    XMLUtils::addGenericChildAsList(doc, node, "Expiries", expiries_);
    XMLUtils::addChild(doc, node, "Calendar", to_string(calendar_));
    XMLUtils::addChild(doc, node, "DayCounter", to_string(dayCounter_));
    XMLUtils::addChild(doc, node, "FXSpotID", fxSpotID_);

    if (dimension_ == Dimension::Smile) {
        XMLUtils::addChild(doc, node, "FXForeignCurveID", fxForeignYieldCurveID_);
        XMLUtils::addChild(doc, node, "FXDomesticCurveID", fxDomesticYieldCurveID_);
    }

    return node;
}
} // namespace data
} // namespace ore

max_stars_repo_name: paul-giltinan/Engine

max_issues_repo_name: paul-giltinan/Engine

max_forks_repo_name: paul-giltinan/Engine


text:
/*

Copyright (c) 2005-2017, University of Oxford.
All rights reserved.

University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.

This file is part of Chaste.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of the University of Oxford nor the names of its
   contributors may be used to endorse or promote products derived from this
   software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TESTVERTEXBASEDDIVISIONRULES_HPP_
#define TESTVERTEXBASEDDIVISIONRULES_HPP_

#include <cxxtest/TestSuite.h>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include "ArchiveOpener.hpp"
#include "CellsGenerator.hpp"
#include "VertexBasedCellPopulation.hpp"
#include "FixedG1GenerationalCellCycleModel.hpp"
#include "AbstractCellBasedTestSuite.hpp"
#include "ShortAxisVertexBasedDivisionRule.hpp"
#include "RandomDirectionVertexBasedDivisionRule.hpp"
#include "FixedVertexBasedDivisionRule.hpp"
#include "HoneycombVertexMeshGenerator.hpp"
#include "SmartPointers.hpp"

// This test is always run sequentially (never in parallel)
#include "FakePetscSetup.hpp"

class TestVertexBasedDivisionRules : public AbstractCellBasedTestSuite
{
public:

    void TestFixedVertexBasedDivisionRule()
    {
        // Make some nodes
        std::vector<Node<2>*> nodes;
        nodes.push_back(new Node<2>(0, true, 2.0, 0.0));
        nodes.push_back(new Node<2>(1, true, 0.0, 2.0));
        nodes.push_back(new Node<2>(2, true, -2.0, 0.0));
        nodes.push_back(new Node<2>(3, true, 0.0, -2.0));

        // Make a rectangular element out of nodes 0,1,2,3
        std::vector<Node<2>*> nodes_elem_1;
        nodes_elem_1.push_back(nodes[0]);
        nodes_elem_1.push_back(nodes[1]);
        nodes_elem_1.push_back(nodes[2]);
        nodes_elem_1.push_back(nodes[3]);

        std::vector<VertexElement<2,2>*> vertex_elements;
        vertex_elements.push_back(new VertexElement<2,2>(0, nodes_elem_1));

        // Make a vertex mesh
        MutableVertexMesh<2,2> vertex_mesh(nodes, vertex_elements);

        TS_ASSERT_EQUALS(vertex_mesh.GetNumElements(), 1u);
        TS_ASSERT_EQUALS(vertex_mesh.GetNumNodes(), 4u);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedG1GenerationalCellCycleModel, 1> cells_generator;
        cells_generator.GenerateBasic(cells, vertex_mesh.GetNumElements());

        // Create a cell population
        VertexBasedCellPopulation<2> cell_population(vertex_mesh, cells);

        CellPtr p_cell0 = cell_population.GetCellUsingLocationIndex(0);

        c_vector<double, 2> expected_vector;
        expected_vector(0) = 6.0/5.0;
        expected_vector(1) = 3.0/5.0;

        TS_ASSERT_THROWS_THIS(new FixedVertexBasedDivisionRule<2>(expected_vector),
            "Input argument must be a unit vector");

        expected_vector(0) = 4.0/5.0;

        // Set the division rule
        MAKE_PTR_ARGS(FixedVertexBasedDivisionRule<2>, p_division_rule_to_set, (expected_vector));
        cell_population.SetVertexBasedDivisionRule(p_division_rule_to_set);

        // Get the division rule back from the population
        boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule = cell_population.GetVertexBasedDivisionRule();

        c_vector<double, 2> division_vector;
        division_vector = boost::static_pointer_cast<FixedVertexBasedDivisionRule<2> >(p_division_rule)->rGetDivisionVector();
        TS_ASSERT_DELTA(division_vector(0), 0.8, 1e-6);
        TS_ASSERT_DELTA(division_vector(1), 0.6, 1e-6);

        c_vector<double, 2> division_vector_again;
        division_vector_again = p_division_rule->CalculateCellDivisionVector(p_cell0, cell_population);
        TS_ASSERT_DELTA(division_vector_again(0), 0.8, 1e-6);
        TS_ASSERT_DELTA(division_vector_again(1), 0.6, 1e-6);
    }

    void TestRandomDirectionVertexBasedDivisionRule()
    {
        /**
         * This tests the RandomDirectionVertexBasedDivisionRule. We first create a vertex based cell population and check whether we can
         * give the division rule to the population and get it back. Then we create 10000 division vectors and check that they point
         * uniformly in random directions.
         */

        // Make some nodes
        std::vector<Node<2>*> nodes;
        nodes.push_back(new Node<2>(0, true, 2.0, 0.0));
        nodes.push_back(new Node<2>(1, true, 0.0, 2.0));
        nodes.push_back(new Node<2>(2, true, -2.0, 0.0));
        nodes.push_back(new Node<2>(3, true, 0.0, -2.0));

        // Make a rectangular element out of nodes 0,1,2,3
        std::vector<Node<2>*> nodes_elem_1;
        nodes_elem_1.push_back(nodes[0]);
        nodes_elem_1.push_back(nodes[1]);
        nodes_elem_1.push_back(nodes[2]);
        nodes_elem_1.push_back(nodes[3]);

        std::vector<VertexElement<2,2>*> vertex_elements;
        vertex_elements.push_back(new VertexElement<2,2>(0, nodes_elem_1));

        // Make a vertex mesh
        MutableVertexMesh<2,2> vertex_mesh(nodes, vertex_elements);

        TS_ASSERT_EQUALS(vertex_mesh.GetNumElements(), 1u);
        TS_ASSERT_EQUALS(vertex_mesh.GetNumNodes(), 4u);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedG1GenerationalCellCycleModel, 1> cells_generator;
        cells_generator.GenerateBasic(cells, vertex_mesh.GetNumElements());

        // Create a cell population
        VertexBasedCellPopulation<2> cell_population(vertex_mesh, cells);

        CellPtr p_cell0 = cell_population.GetCellUsingLocationIndex(0);

        // Set the division rule for our population to be the random direction division rule
        boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule_to_set(new RandomDirectionVertexBasedDivisionRule<2>());
        cell_population.SetVertexBasedDivisionRule(p_division_rule_to_set);

        // Get the division rule back from the population
        boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule = cell_population.GetVertexBasedDivisionRule();

        // Get 10000 division vectors, check each length, their mean and their variance.
        c_vector<double, 2> average_axis = zero_vector<double>(2);
        c_vector<double, 2> axis_variance = zero_vector<double>(2);
        double average_angle = 0.0;
        double angle_variance = 0.0;
        for (unsigned iteration = 0; iteration < 10000; iteration++)
        {
            c_vector<double, 2> random_axis = p_division_rule->CalculateCellDivisionVector(p_cell0, cell_population);
            TS_ASSERT_DELTA(norm_2(random_axis), 1.0,1e-6);
            average_axis(0) += random_axis(0);
            axis_variance(0) += random_axis(0)*random_axis(0);
            average_axis(1) += random_axis(1);
            axis_variance(1) += random_axis(1)*random_axis(1);
            average_angle += asin(random_axis(0));
            angle_variance += asin(random_axis(0))*asin(random_axis(0));
        }
        average_axis(0) /= 10000.0;
        average_axis(1) /= 10000.0;
        axis_variance(0) /= 10000.0;
        axis_variance(1) /= 10000.0;
        average_angle /= 10000.0;
        angle_variance /= 10000.0;

        TS_ASSERT_DELTA(average_axis(0), 0.0, 1e-2);
        TS_ASSERT_DELTA(average_axis(1), 0.0, 1e-2);
        TS_ASSERT_DELTA(axis_variance(0), 0.5, 1e-2);
        TS_ASSERT_DELTA(axis_variance(1), 0.5, 1e-2);
        TS_ASSERT_DELTA(average_angle, 0.0, 1e-2);
        TS_ASSERT_DELTA(angle_variance, M_PI*M_PI/12.0, 1e-2);
    }

    void TestShortAxisVertexBasedDivisionRule()
    {
        // Create a vertex mesh
        std::vector<Node<2>*> nodes;
        nodes.push_back(new Node<2>(0, true, 2.0, -1.0));
        nodes.push_back(new Node<2>(1, true, 2.0, 1.0));
        nodes.push_back(new Node<2>(2, true, -2.0, 1.0));
        nodes.push_back(new Node<2>(3, true, -2.0, -1.0));
        nodes.push_back(new Node<2>(4, true, 0.0, 2.0));

        std::vector<Node<2>*> nodes_elem_1;
        nodes_elem_1.push_back(nodes[0]);
        nodes_elem_1.push_back(nodes[1]);
        nodes_elem_1.push_back(nodes[2]);
        nodes_elem_1.push_back(nodes[3]);

        std::vector<Node<2>*> nodes_elem_2;
        nodes_elem_2.push_back(nodes[1]);
        nodes_elem_2.push_back(nodes[4]);
        nodes_elem_2.push_back(nodes[2]);

        std::vector<VertexElement<2,2>*> vertex_elements;
        vertex_elements.push_back(new VertexElement<2,2>(0, nodes_elem_1));
        vertex_elements.push_back(new VertexElement<2,2>(1, nodes_elem_2));

        MutableVertexMesh<2,2> vertex_mesh(nodes, vertex_elements);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedG1GenerationalCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, vertex_mesh.GetNumElements());

        // Create cell population
        VertexBasedCellPopulation<2> cell_population(vertex_mesh, cells);

        // Note: ShortAxisVertexBasedDivisionRule is the default division rule for vertex-based cell populations

        CellPtr p_cell0 = cell_population.GetCellUsingLocationIndex(0);

        // Get the division rule back from the population
        boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule = cell_population.GetVertexBasedDivisionRule();
        c_vector<double, 2> short_axis = p_division_rule->CalculateCellDivisionVector(p_cell0, cell_population);

        TS_ASSERT_DELTA(short_axis[0], 0.0, 1e-9);
        TS_ASSERT_DELTA(short_axis[1], 1.0, 1e-9);
    }

    void TestArchiveFixedVertexBasedDivisionRule() throw(Exception)
    {
        FileFinder archive_dir("archive", RelativeTo::ChasteTestOutput);
        std::string archive_file = "FixedVertexBasedDivisionRule.arch";

        // Create data structures to store variables to test for equality here
        {
            c_vector<double, 2> vector;
            vector(0) = 5.0/13.0;
            vector(1) = 12.0/13.0;
            boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule(new FixedVertexBasedDivisionRule<2>(vector));

            // Create output archive
            ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive();

            // Record values to test into data structures
            (*p_arch) << p_division_rule;
        }

        {
            boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule;

            ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive();

            // Restore from the archive
            (*p_arch) >> p_division_rule;

            TS_ASSERT(dynamic_cast<FixedVertexBasedDivisionRule<2>*>(p_division_rule.get()));

            c_vector<double, 2> location;
            location = (dynamic_cast<FixedVertexBasedDivisionRule<2>*>(p_division_rule.get()))->rGetDivisionVector();
            TS_ASSERT_DELTA(location[0], 5.0/13.0, 1e-6);
            TS_ASSERT_DELTA(location[1], 12.0/13.0, 1e-6);
        }
    }

    void TestArchiveRandomDirectionVertexBasedDivisionRule() throw(Exception)
    {
        FileFinder archive_dir("archive", RelativeTo::ChasteTestOutput);
        std::string archive_file = "RandomDirectionVertexBasedDivisionRule.arch";

        // Create data structures to store variables to test for equality here
        {
            boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule(new RandomDirectionVertexBasedDivisionRule<2>());

            // Create output archive
            ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive();

            // Record values to test into data structures
            (*p_arch) << p_division_rule;
        }

        {
            boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule;

            // Create an input archive
            ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive();

            // Restore from the archive
            (*p_arch) >> p_division_rule;

            TS_ASSERT(dynamic_cast<RandomDirectionVertexBasedDivisionRule<2>*>(p_division_rule.get()));
        }
    }

    void TestArchiveShortAxisVertexBasedDivisionRule() throw(Exception)
    {
        FileFinder archive_dir("archive", RelativeTo::ChasteTestOutput);
        std::string archive_file = "ShortAxisVertexBasedDivisionRule.arch";

        // Create data structures to store variables to test for equality here
        {
            boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule(new ShortAxisVertexBasedDivisionRule<2>());

            // Create output archive
            ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive();

            // Record values to test into data structures
            (*p_arch) << p_division_rule;
        }

        {
            boost::shared_ptr<AbstractVertexBasedDivisionRule<2> > p_division_rule;

            // Create an input archive
            ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive();

            // Restore from the archive
            (*p_arch) >> p_division_rule;

            TS_ASSERT(dynamic_cast<ShortAxisVertexBasedDivisionRule<2>*>(p_division_rule.get()));
        }
    }
};

#endif /*TESTVERTEXBASEDDIVISIONRULES_HPP_*/

max_stars_repo_name: gonayl/Chaste

max_issues_repo_name: gonayl/Chaste

max_forks_repo_name: gonayl/Chaste


text:
// Copyright (C) 2008-2018 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0 (see accompanying
// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html

#include <boost/contract.hpp>
#include <boost/type_traits.hpp>
#include <boost/noncopyable.hpp>
#include <cassert>

//[old_if_copyable_offset
template<typename T> // T might or might not be copyable.
void offset(T& x, int count) {
    // No compiler error if T has no copy constructor...
    boost::contract::old_ptr_if_copyable<T> old_x = BOOST_CONTRACT_OLDOF(x);
    boost::contract::check c = boost::contract::function()
        .postcondition([&] {
            // ...but old value null if T has no copy constructor.
            if(old_x) BOOST_CONTRACT_ASSERT(x == *old_x + count);
        })
    ;

    x += count;
}
//]

//[old_if_copyable_w_decl
// Copyable type but...
class w {
public:
    w(w const&) { /* Some very expensive copy here operation here... */ }

    /* ... */
//]
    w() : num_(0) {}
    int operator+(int i) const { return num_ + i; }
    w& operator+=(int i) { num_ += i; return *this; }
    bool operator==(int i) const { return long(num_) == i; }
private:
    unsigned long num_;
};

//[old_if_copyable_w_spec
// ...never copy old values for type `w` (because its copy is too expensive).
namespace boost { namespace contract {
    template<>
    struct is_old_value_copyable<w> : boost::false_type {};
} }
//]

//[old_if_copyable_p_decl
// Non-copyable type but...
class p : private boost::noncopyable {
    int* num_;

    friend struct boost::contract::old_value_copy<p>;

    /* ... */
//]
public:
    p() : num_(new int(0)) {}
    ~p() { delete num_; }
    int operator+(int i) const { return *num_ + i; }
    p& operator+=(int i) { *num_ += i; return *this; }
    bool operator==(int i) const { return *num_ == i; }
};

//[old_if_copyable_p_spec
// ...still copy old values for type `p` (using a deep copy).
namespace boost { namespace contract {
    template<>
    struct old_value_copy<p> {
        explicit old_value_copy(p const& old) {
            *old_.num_ = *old.num_; // Deep copy pointed value.
        }

        p const& old() const { return old_; }

    private:
        p old_;
    };

    template<>
    struct is_old_value_copyable<p> : boost::true_type {};
} }
//]

//[old_if_copyable_n_decl
class n { // Do not want to use boost::noncopyable but...
    int num_;

private:
    n(n const&); // ...unimplemented private copy constructor (so non-copyable).

    /* ... */
//]

public:
    n() : num_(0) {}
    int operator+(int i) const { return num_ + i; }
    n& operator+=(int i) { num_ += i; return *this; }
    bool operator==(int i) const { return num_ == i; }
};

//[old_if_copyable_n_spec
// Specialize `boost::is_copy_constructible` (no need for this on C++11).
namespace boost { namespace contract {
    template<>
    struct is_old_value_copyable<n> : boost::false_type {};
} }
//]

int main() {
    int i = 0; // Copy constructor, copy and check old values.
    offset(i, 3);
    assert(i == 3);

    w j; // Expensive copy constructor, so never copy or check old values.
    offset(j, 3);
    assert(j == 3);

    p k; // No copy constructor, but still copy and check old values.
    offset(k, 3);
    assert(k == 3);

    n h; // No copy constructor, no compiler error but no old value checks.
    offset(h, 3);
    assert(h == 3);

    return 0;
}


text:
#include "camera_array/SystemModels.h"
#include <boost/foreach.hpp>

#define POSE_DIM (PoseSE3::TangentDimension)

namespace argus
{

InstantCameraTransitionFunction::InstantCameraTransitionFunction( unsigned int maxCams )
: maxActiveCams( maxCams ) {}

CameraArrayState InstantCameraTransitionFunction::Transition( const CameraArrayState& state,
                                                              const CameraArrayAction& action )
{
	CameraArrayState next( state );

	switch( action.type )
	{
		case CameraArrayAction::DO_NOTHING:

			// Do as it says!
			break;

		case CameraArrayAction::ACTIVATE_CAMERA:

			// If the target is not active and we have fewer than max, it activates
			if( state.IsInactive( action.toActivate ) &&
				state.activeCameras.size() < maxActiveCams )
			{
				next.Activate( action.toActivate );
			}

			// Else nothing happens
			break;

		case CameraArrayAction::DEACTIVATE_CAMERA:

			// If the target is active, it deactivates
			if( state.IsActive( action.toDeactivate ) )
			{
				next.Deactivate( action.toDeactivate );
			}

			// Else nothing happens
			break;

		case CameraArrayAction::SWITCH_CAMERAS:

			// If the target cameras are in their valid states, switch them
			if( state.IsActive( action.toDeactivate ) &&
				state.IsInactive( action.toActivate ) )
			{
				next.Activate( action.toActivate );
				next.Deactivate( action.toDeactivate );
			}

			// Else nothing happens
			break;
	}
	return next;
}

SwitchingCameraActionGenerator::SwitchingCameraActionGenerator( unsigned int maxCams )
: maxActiveCams( maxCams ) {}

SwitchingCameraActionGenerator::ActionList
SwitchingCameraActionGenerator::GetActions( const CameraArrayState& state )
{
	ActionList actions;

	CameraArrayAction action;

	// First activate all cameras if allowed
	if( state.activeCameras.size() < maxActiveCams )
	{
		action.type = CameraArrayAction::ACTIVATE_CAMERA;
		BOOST_FOREACH( const std::string& name, state.inactiveCameras )
		{
			action.toActivate = name;
			actions.push_back( action );
		}
	}
	// Otherwise allow null action
	else
	{
		action.type = CameraArrayAction::DO_NOTHING;
		actions.push_back( action );
	}

	// Now switch for all combinations
	action.type = CameraArrayAction::SWITCH_CAMERAS;
	BOOST_FOREACH( const std::string& active, state.activeCameras )
	{
		action.toDeactivate = active;
		BOOST_FOREACH( const std::string& inactive, state.inactiveCameras )
		{
			action.toActivate = inactive;
			actions.push_back( action );
		}
	}

	return actions;
}

FixedStepTargetTransitionFunction::FixedStepTargetTransitionFunction( double timestep )
: dt( timestep )
{}

TargetState
FixedStepTargetTransitionFunction::Transition( const TargetState& state,
                                               const AccelerationAction& action )
{
	TargetState next( state );
	PoseSE3::TangentDim velocity = state.derivatives.head<POSE_DIM>();
	PoseSE3 displacement = PoseSE3::Exp( dt * velocity +
	                                     0.5 * dt * dt * action.acceleration );
	next.pose = state.pose * displacement;
	next.derivatives = velocity + dt * action.acceleration;
	return next;
}

FixedTargetActionGenerator::FixedTargetActionGenerator( const AccelerationAction& o )
: output( o ) {}

std::vector<AccelerationAction> FixedTargetActionGenerator::GetActions( const TargetState& state )
{
	std::vector<AccelerationAction> outputs;
	outputs.push_back( output );
	return outputs;
}

MixedTransitionFunction::MixedTransitionFunction( const TargetTransitionFunction::Ptr& tfunc,
                                                  const ArrayTransitionFunction::Ptr& afunc )
: targetTransition( tfunc ), arrayTransition( afunc ) {}

RobotTargetState MixedTransitionFunction::Transition( const RobotTargetState& state,
                                                      const CameraArrayAction& action )
{
	RobotTargetState next( state );
	next.array = arrayTransition->Transition( state.array, action );

	AccelerationAction defaultAcceleration;
	next.robot = targetTransition->Transition( state.robot, defaultAcceleration );
// 	BOOST_FOREACH( const RobotTargetAction::ActionMap::value_type& item, action.targetActions )
	BOOST_FOREACH( const RobotTargetState::TargetMap::value_type& item, state.targets )
	{
		const std::string& targetName = item.first;
// 		const AccelerationAction& targetAction = item.second;
		AccelerationAction targetAction;
		next.targets[ targetName ] = targetTransition->Transition( state.targets.at( targetName ),
		                                                           targetAction );
	}
	return next;
}

}

max_stars_repo_name: Humhu/argus

max_issues_repo_name: Humhu/argus

max_forks_repo_name: Humhu/argus


text:
#ifndef INCLUDE_PACKET_HPP_
#define INCLUDE_PACKET_HPP_

#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include "message.hpp"

using boost::asio::ip::tcp;
using boost::system::error_code;

class Packet
{
public:
    Packet();

    Packet( const unsigned int version,
            const unsigned int type,
            const unsigned int length,
            const std::string& message );

    const unsigned int getVersion() const;
    const unsigned int getMsgType() const;
    const unsigned int getLength () const;
    const unsigned int getHdrSize() const;
    const unsigned int getMsgSize() const;
    const unsigned int getPktSize() const;
    const std::string& getMessage() const;

    void setVersion( const unsigned int version );
    void setType   ( const unsigned int type    );
    void setLength ( const unsigned int length  );
    void setMessage( const std::string& message );

    void set ( const unsigned int version,
               const unsigned int type,
               const unsigned int length );

    void set ( const unsigned int version,
               const unsigned int type,
               const unsigned int length,
               const std::string& message );

    error_code recv( tcp::socket& socket );
    error_code send( tcp::socket& socket );

    error_code processPackets( tcp::socket& socket );

    friend std::ostream& operator<<( std::ostream& os, const Packet& packet );

private:
    bool isValidVersion();
    bool isValidMsgType();

    struct Header
    {
        enum { VERSION_SIZE = 3, TYPE_SIZE = 5, LENGTH_SIZE = 16 };

        unsigned int    _version : VERSION_SIZE;
        unsigned int    _type    : TYPE_SIZE;
        unsigned int    _length  : LENGTH_SIZE;
    };

    Header              _header;
    std::string         _message;
};

#endif /* INCLUDE_PACKET_HPP_ */

max_stars_repo_name: YddEd/TcpClientServerApp

max_issues_repo_name: YddEd/TcpClientServerApp

max_forks_repo_name: YddEd/TcpClientServerApp