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

#include <errors.hpp>
#include <string.hpp>
#include <algorithms.hpp>

#include <directory_entry.hpp>
#include <mount_point.hpp>

#include "vfs/vfs.hpp"
#include "vfs/file_system.hpp"

#include "fs/fat32.hpp"
#include "fs/sysfs.hpp"

#include "scheduler.hpp"
#include "flags.hpp"

#include "console.hpp"

namespace {

struct mounted_fs {
    vfs::partition_type fs_type;
    std::string device;
    std::string mount_point;
    vfs::file_system* file_system;

    std::vector<std::string> mp_vec;

    mounted_fs() = default;

    mounted_fs(vfs::partition_type type, const char* dev, const char* mp, vfs::file_system* fs) :
        fs_type(type), device(dev), mount_point(mp), file_system(fs)
    {
        mp_vec = std::split(mount_point, '/');
    }
};

std::string partition_type_to_string(vfs::partition_type type){
    switch(type){
        case vfs::partition_type::FAT32:
            return "FAT32";
        case vfs::partition_type::SYSFS:
            return "sysfs";
        case vfs::partition_type::UNKNOWN:
            return "Unknown";
        default:
            return "Invalid Type";
    }
}

std::vector<mounted_fs> mount_point_list;

void mount_root(){
    //TODO Get information about the root from a confgiuration file
    mount(vfs::partition_type::FAT32, "/", "TODO");
}

void mount_sys(){
    mount(vfs::partition_type::SYSFS, "/sys/", "none");
}

std::vector<std::string> get_path(const char* file_path){
    std::string file(file_path);

    std::vector<std::string> path;

    if(file[0] != '/'){
        for(auto& part : scheduler::get_working_directory()){
            path.push_back(part);
        }
    }

    auto parts = std::split(file, '/');
    for(auto& part : parts){
        path.push_back(part);
    }

    return std::move(path);
}

mounted_fs& get_fs(const std::vector<std::string>& path){
    size_t best = 0;
    size_t best_match = 0;

    for(size_t i = 0; i < mount_point_list.size(); ++i){
        auto& mp = mount_point_list[i];

        bool match = true;
        for(size_t j = 0; j < mp.mp_vec.size() && j < path.size() ; ++j){
            if(mp.mp_vec[j] != path[j]){
                match = false;
                break;
            }
        }

        if(match && mp.mp_vec.size() > best){
            best = mp.mp_vec.size();
            best_match = i;
        }
    }

    return mount_point_list[best_match];;
}

std::vector<std::string> get_fs_path(const std::vector<std::string>& path, const mounted_fs& fs){
    std::vector<std::string> fs_path;

    for(size_t i = fs.mp_vec.size(); i < path.size(); ++i){
        fs_path.push_back(path[i]);
    }

    return std::move(fs_path);
}

} //end of anonymous namespace

void vfs::init(){
    mount_root();
    mount_sys();
}

int64_t vfs::mount(partition_type type, const char* mount_point, const char* device){
    file_system* fs = nullptr;

    switch(type){
        case vfs::partition_type::FAT32:
            fs = new fat32::fat32_file_system(0, 0);

            break;

        case vfs::partition_type::SYSFS:
            fs = new sysfs::sysfs_file_system(mount_point);

            break;

        default:
            return -std::ERROR_INVALID_FILE_SYSTEM;
    }

    mount_point_list.emplace_back(type, device, mount_point, fs);

    return 0;
}

int64_t vfs::statfs(const char* mount_point, statfs_info& info){
    if(std::str_len(mount_point) == 0){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(mount_point);
    auto& fs = get_fs(path);

    return fs.file_system->statfs(info);
}

int64_t vfs::open(const char* file_path, size_t flags){
    std::string file(file_path);

    if(file.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(file_path);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    //Special handling for opening the root
    if(path.empty()){
        return scheduler::register_new_handle(path);
    }

    if(flags & std::OPEN_CREATE){
        return fs.file_system->touch(fs_path);
    } else {
        vfs::file file;
        auto result = fs.file_system->get_file(fs_path, file);

        if(result > 0){
            return -result;
        } else {
            return scheduler::register_new_handle(path);
        }
    }
}

void vfs::close(size_t fd){
    if(scheduler::has_handle(fd)){
        scheduler::release_handle(fd);
    }
}

int64_t vfs::mkdir(const char* file_path){
    std::string file(file_path);

    if(file.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(file_path);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    return fs.file_system->mkdir(fs_path);
}

int64_t vfs::rm(const char* file_path){
    std::string file(file_path);

    if(file.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(file_path);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    return fs.file_system->rm(fs_path);
}

int64_t vfs::stat(size_t fd, stat_info& info){
    if(!scheduler::has_handle(fd)){
        return -std::ERROR_INVALID_FILE_DESCRIPTOR;
    }

    auto path = scheduler::get_handle(fd);

    //Special handling for root
    if(path.empty()){
        //TODO Add file system support for stat of the root directory
        info.size = 4096;
        info.flags = STAT_FLAG_DIRECTORY;

        return 0;
    }

    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    vfs::file f;
    auto result = fs.file_system->get_file(fs_path, f);

    if(result > 0){
        return -result;
    }

    info.size = f.size;
    info.flags = 0;

    if(f.directory){
        info.flags |= STAT_FLAG_DIRECTORY;
    }

    if(f.system){
        info.flags |= STAT_FLAG_SYSTEM;
    }

    if(f.hidden){
        info.flags |= STAT_FLAG_HIDDEN;
    }

    info.created = f.created;
    info.modified = f.modified;
    info.accessed = f.accessed;

    return 0;
}

int64_t vfs::read(size_t fd, char* buffer, size_t count, size_t offset){
    if(!scheduler::has_handle(fd)){
        return -std::ERROR_INVALID_FILE_DESCRIPTOR;
    }

    auto path = scheduler::get_handle(fd);

    if(path.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    size_t read = 0;
    auto result = fs.file_system->read(fs_path, buffer, count, offset, read);

    if(result > 0){
        return -result;
    }

    return read;
}

int64_t vfs::direct_read(const std::string& file_path, std::string& content){
    auto path = get_path(file_path.c_str());
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    vfs::file f;
    auto result = fs.file_system->get_file(fs_path, f);

    if(result > 0){
        return -result;
    }

    content.reserve(f.size + 1);

    size_t read = 0;
    result = fs.file_system->read(fs_path, content.c_str(), f.size, 0, read);

    if(result > 0){
        return -result;
    }

    content[read] = '\0';
    content.adjust_size(read);

    return read;
}

int64_t vfs::entries(size_t fd, char* buffer, size_t size){
    if(!scheduler::has_handle(fd)){
        return -std::ERROR_INVALID_FILE_DESCRIPTOR;
    }

    auto path = scheduler::get_handle(fd);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    std::vector<vfs::file> files;
    auto result = fs.file_system->ls(fs_path, files);

    if(result > 0){
        return -result;
    }

    size_t total_size = 0;

    for(auto& f : files){
        total_size += sizeof(directory_entry) + f.file_name.size();
    }

    if(size < total_size){
        return -std::ERROR_BUFFER_SMALL;
    }

    size_t position = 0;

    for(size_t i = 0; i < files.size(); ++i){
        auto& file = files[i];

        auto entry = reinterpret_cast<directory_entry*>(buffer + position);

        entry->type = 0; //TODO Fill that
        entry->length = file.file_name.size();

        if(i + 1 < files.size()){
            entry->offset_next = file.file_name.size() + 1 + 3 * 8;
            position += entry->offset_next;
        } else {
            entry->offset_next = 0;
        }

        char* name_buffer = &(entry->name);
        for(size_t j = 0; j < file.file_name.size(); ++j){
            name_buffer[j] = file.file_name[j];
        }
        name_buffer[file.file_name.size()] = '\0';
    }

    return total_size;
}

int64_t vfs::mounts(char* buffer, size_t size){
    size_t total_size = 0;

    for(auto& mp : mount_point_list){
        total_size += 4 * sizeof(size_t) + 3 + mp.device.size() + mp.mount_point.size() + partition_type_to_string(mp.fs_type).size();
    }

    if(size < total_size){
        return -std::ERROR_BUFFER_SMALL;
    }

    size_t position = 0;

    for(size_t i = 0; i < mount_point_list.size(); ++i){
        auto& mp = mount_point_list[i];

        auto entry = reinterpret_cast<mount_point*>(buffer + position);

        auto fs_type = partition_type_to_string(mp.fs_type);

        entry->length_mp = mp.mount_point.size();
        entry->length_dev = mp.device.size();
        entry->length_type = fs_type.size();

        if(i + 1 < mount_point_list.size()){
            entry->offset_next = 4 * sizeof(size_t) + 3 + mp.device.size() + mp.mount_point.size() + fs_type.size();
            position += entry->offset_next;
        } else {
            entry->offset_next = 0;
        }

        char* name_buffer = &(entry->name);
        size_t str_pos = 0;

        for(size_t j = 0; j < mp.mount_point.size(); ++j){
            name_buffer[str_pos++] = mp.mount_point[j];
        }
        name_buffer[str_pos++] = '\0';
        for(size_t j = 0; j < mp.device.size(); ++j){
            name_buffer[str_pos++] = mp.device[j];
        }
        name_buffer[str_pos++] = '\0';
        for(size_t j = 0; j < fs_type.size(); ++j){
            name_buffer[str_pos++] = fs_type[j];
        }
        name_buffer[str_pos++] = '\0';
    }

    return total_size;
}
<commit_msg>Fix handling of /<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <errors.hpp>
#include <string.hpp>
#include <algorithms.hpp>

#include <directory_entry.hpp>
#include <mount_point.hpp>

#include "vfs/vfs.hpp"
#include "vfs/file_system.hpp"

#include "fs/fat32.hpp"
#include "fs/sysfs.hpp"

#include "scheduler.hpp"
#include "flags.hpp"

#include "console.hpp"

namespace {

struct mounted_fs {
    vfs::partition_type fs_type;
    std::string device;
    std::string mount_point;
    vfs::file_system* file_system;

    std::vector<std::string> mp_vec;

    mounted_fs() = default;

    mounted_fs(vfs::partition_type type, const char* dev, const char* mp, vfs::file_system* fs) :
        fs_type(type), device(dev), mount_point(mp), file_system(fs)
    {
        mp_vec = std::split(mount_point, '/');
    }
};

std::string partition_type_to_string(vfs::partition_type type){
    switch(type){
        case vfs::partition_type::FAT32:
            return "FAT32";
        case vfs::partition_type::SYSFS:
            return "sysfs";
        case vfs::partition_type::UNKNOWN:
            return "Unknown";
        default:
            return "Invalid Type";
    }
}

std::vector<mounted_fs> mount_point_list;

void mount_root(){
    //TODO Get information about the root from a confgiuration file
    mount(vfs::partition_type::FAT32, "/", "TODO");
}

void mount_sys(){
    mount(vfs::partition_type::SYSFS, "/sys/", "none");
}

std::vector<std::string> get_path(const char* file_path){
    std::string file(file_path);

    std::vector<std::string> path;

    if(file[0] != '/'){
        for(auto& part : scheduler::get_working_directory()){
            path.push_back(part);
        }
    }

    auto parts = std::split(file, '/');
    for(auto& part : parts){
        path.push_back(part);
    }

    return std::move(path);
}

mounted_fs& get_fs(const std::vector<std::string>& path){
    size_t best = 0;
    size_t best_match = 0;

    if(path.empty()){
        for(auto& mp : mount_point_list){
            if(mp.mp_vec.empty()){
                return mp;
            }
        }
    }

    for(size_t i = 0; i < mount_point_list.size(); ++i){
        auto& mp = mount_point_list[i];

        bool match = true;
        for(size_t j = 0; j < mp.mp_vec.size() && j < path.size() ; ++j){
            if(mp.mp_vec[j] != path[j]){
                match = false;
                break;
            }
        }

        if(match && mp.mp_vec.size() > best){
            best = mp.mp_vec.size();
            best_match = i;
        }
    }

    return mount_point_list[best_match];;
}

std::vector<std::string> get_fs_path(const std::vector<std::string>& path, const mounted_fs& fs){
    std::vector<std::string> fs_path;

    for(size_t i = fs.mp_vec.size(); i < path.size(); ++i){
        fs_path.push_back(path[i]);
    }

    return std::move(fs_path);
}

} //end of anonymous namespace

void vfs::init(){
    mount_root();
    mount_sys();
}

int64_t vfs::mount(partition_type type, const char* mount_point, const char* device){
    file_system* fs = nullptr;

    switch(type){
        case vfs::partition_type::FAT32:
            fs = new fat32::fat32_file_system(0, 0);

            break;

        case vfs::partition_type::SYSFS:
            fs = new sysfs::sysfs_file_system(mount_point);

            break;

        default:
            return -std::ERROR_INVALID_FILE_SYSTEM;
    }

    mount_point_list.emplace_back(type, device, mount_point, fs);

    return 0;
}

int64_t vfs::statfs(const char* mount_point, statfs_info& info){
    if(std::str_len(mount_point) == 0){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(mount_point);
    auto& fs = get_fs(path);

    return fs.file_system->statfs(info);
}

int64_t vfs::open(const char* file_path, size_t flags){
    std::string file(file_path);

    if(file.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(file_path);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    //Special handling for opening the root
    if(path.empty()){
        return scheduler::register_new_handle(path);
    }

    if(flags & std::OPEN_CREATE){
        return fs.file_system->touch(fs_path);
    } else {
        vfs::file file;
        auto result = fs.file_system->get_file(fs_path, file);

        if(result > 0){
            return -result;
        } else {
            return scheduler::register_new_handle(path);
        }
    }
}

void vfs::close(size_t fd){
    if(scheduler::has_handle(fd)){
        scheduler::release_handle(fd);
    }
}

int64_t vfs::mkdir(const char* file_path){
    std::string file(file_path);

    if(file.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(file_path);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    return fs.file_system->mkdir(fs_path);
}

int64_t vfs::rm(const char* file_path){
    std::string file(file_path);

    if(file.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto path = get_path(file_path);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    return fs.file_system->rm(fs_path);
}

int64_t vfs::stat(size_t fd, stat_info& info){
    if(!scheduler::has_handle(fd)){
        return -std::ERROR_INVALID_FILE_DESCRIPTOR;
    }

    auto path = scheduler::get_handle(fd);

    //Special handling for root
    if(path.empty()){
        //TODO Add file system support for stat of the root directory
        info.size = 4096;
        info.flags = STAT_FLAG_DIRECTORY;

        return 0;
    }

    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    vfs::file f;
    auto result = fs.file_system->get_file(fs_path, f);

    if(result > 0){
        return -result;
    }

    info.size = f.size;
    info.flags = 0;

    if(f.directory){
        info.flags |= STAT_FLAG_DIRECTORY;
    }

    if(f.system){
        info.flags |= STAT_FLAG_SYSTEM;
    }

    if(f.hidden){
        info.flags |= STAT_FLAG_HIDDEN;
    }

    info.created = f.created;
    info.modified = f.modified;
    info.accessed = f.accessed;

    return 0;
}

int64_t vfs::read(size_t fd, char* buffer, size_t count, size_t offset){
    if(!scheduler::has_handle(fd)){
        return -std::ERROR_INVALID_FILE_DESCRIPTOR;
    }

    auto path = scheduler::get_handle(fd);

    if(path.empty()){
        return -std::ERROR_INVALID_FILE_PATH;
    }

    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    size_t read = 0;
    auto result = fs.file_system->read(fs_path, buffer, count, offset, read);

    if(result > 0){
        return -result;
    }

    return read;
}

int64_t vfs::direct_read(const std::string& file_path, std::string& content){
    auto path = get_path(file_path.c_str());
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    vfs::file f;
    auto result = fs.file_system->get_file(fs_path, f);

    if(result > 0){
        return -result;
    }

    content.reserve(f.size + 1);

    size_t read = 0;
    result = fs.file_system->read(fs_path, content.c_str(), f.size, 0, read);

    if(result > 0){
        return -result;
    }

    content[read] = '\0';
    content.adjust_size(read);

    return read;
}

int64_t vfs::entries(size_t fd, char* buffer, size_t size){
    if(!scheduler::has_handle(fd)){
        return -std::ERROR_INVALID_FILE_DESCRIPTOR;
    }

    auto path = scheduler::get_handle(fd);
    auto& fs = get_fs(path);
    auto fs_path = get_fs_path(path, fs);

    std::vector<vfs::file> files;
    auto result = fs.file_system->ls(fs_path, files);

    if(result > 0){
        return -result;
    }

    size_t total_size = 0;

    for(auto& f : files){
        total_size += sizeof(directory_entry) + f.file_name.size();
    }

    if(size < total_size){
        return -std::ERROR_BUFFER_SMALL;
    }

    size_t position = 0;

    for(size_t i = 0; i < files.size(); ++i){
        auto& file = files[i];

        auto entry = reinterpret_cast<directory_entry*>(buffer + position);

        entry->type = 0; //TODO Fill that
        entry->length = file.file_name.size();

        if(i + 1 < files.size()){
            entry->offset_next = file.file_name.size() + 1 + 3 * 8;
            position += entry->offset_next;
        } else {
            entry->offset_next = 0;
        }

        char* name_buffer = &(entry->name);
        for(size_t j = 0; j < file.file_name.size(); ++j){
            name_buffer[j] = file.file_name[j];
        }
        name_buffer[file.file_name.size()] = '\0';
    }

    return total_size;
}

int64_t vfs::mounts(char* buffer, size_t size){
    size_t total_size = 0;

    for(auto& mp : mount_point_list){
        total_size += 4 * sizeof(size_t) + 3 + mp.device.size() + mp.mount_point.size() + partition_type_to_string(mp.fs_type).size();
    }

    if(size < total_size){
        return -std::ERROR_BUFFER_SMALL;
    }

    size_t position = 0;

    for(size_t i = 0; i < mount_point_list.size(); ++i){
        auto& mp = mount_point_list[i];

        auto entry = reinterpret_cast<mount_point*>(buffer + position);

        auto fs_type = partition_type_to_string(mp.fs_type);

        entry->length_mp = mp.mount_point.size();
        entry->length_dev = mp.device.size();
        entry->length_type = fs_type.size();

        if(i + 1 < mount_point_list.size()){
            entry->offset_next = 4 * sizeof(size_t) + 3 + mp.device.size() + mp.mount_point.size() + fs_type.size();
            position += entry->offset_next;
        } else {
            entry->offset_next = 0;
        }

        char* name_buffer = &(entry->name);
        size_t str_pos = 0;

        for(size_t j = 0; j < mp.mount_point.size(); ++j){
            name_buffer[str_pos++] = mp.mount_point[j];
        }
        name_buffer[str_pos++] = '\0';
        for(size_t j = 0; j < mp.device.size(); ++j){
            name_buffer[str_pos++] = mp.device[j];
        }
        name_buffer[str_pos++] = '\0';
        for(size_t j = 0; j < fs_type.size(); ++j){
            name_buffer[str_pos++] = fs_type[j];
        }
        name_buffer[str_pos++] = '\0';
    }

    return total_size;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include "Poco/Util/Application.h"
#include "Poco/Dynamic/Struct.h"
#include "Poco/JSON/Object.h"

#include "MQ/MQSubsystem.h"
#include "MQ/MQException.h"

#include "MQ/Web/MQController.h"
#include "MQ/Web/MQMapper.h"
#include "MQ/Web/TemplateView.h"
#include "MQ/Web/JSONView.h"

namespace MQ {
namespace Web {

MQController::MQController() : Controller(), _mqwebData(new Poco::JSON::Object()), _commandServer(NULL)
{
	set("mqweb", _mqwebData);
}

MQController::~MQController()
{
}

void MQController::beforeAction()
{
	_stopwatch.start();

	Poco::JSON::Object::Ptr date = new Poco::JSON::Object();
	_mqwebData->set("date", date);
	date->set("start", Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT));

	MQSubsystem& mqSystem = Poco::Util::Application::instance().getSubsystem<MQSubsystem>();
	Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();

	_mqwebData->set("client", mqSystem.client());

	std::string qmgrName;
	if ( config.hasProperty("mq.web.qmgr") )
	{
		// When a queuemanager is passed on the command line, we always
		// connect to this queuemanager. When the user specified another
		// queuemanager on the URL, it will be ignored.
		qmgrName = config.getString("mq.web.qmgr");
	}
	else
	{
		const std::vector<std::string>& parameters = getParameters();
		if ( parameters.size() > 0 )
		{
			qmgrName = parameters[0];
		}
		else if ( mqSystem.client() )
		{
			qmgrName = config.getString("mq.web.defaultQmgr", "*");
		}
	}

	Poco::SharedPtr<QueueManagerPool> qmgrPool = QueueManagerPoolCache::instance()->getQueueManagerPool(qmgrName);
	if ( qmgrPool.isNull() )
	{
		//TODO: out of memory ???
	}

	QueueManager::Ptr qmgr = qmgrPool->borrowObject();
	if ( qmgr.isNull() )
	{
		//TODO: out of memory???
	}
	_qmgrPoolGuard = new QueueManagerPoolGuard(qmgrPool, qmgr);

	_mqwebData->set("qmgr", qmgr->name());
	_mqwebData->set("zos", qmgr->zos());
	_mqwebData->set("qmgrId", qmgr->id());

	_commandServer = qmgr->commandServer();
	if ( _commandServer == NULL )
	{
		std::string qmgrConfigReplyQ = "mq.web.qmgr." + qmgrName + ".reply";

		std::string replyQ;
		if ( config.has(qmgrConfigReplyQ) )
		{
			replyQ = config.getString(qmgrConfigReplyQ);
		}
		else
		{
			replyQ = config.getString("mq.web.reply", "SYSTEM.DEFAULT.MODEL.QUEUE");
		}
		_commandServer = qmgr->createCommandServer(replyQ);
	}

	if ( _commandServer != NULL )
	{
		_mqwebData->set("replyq", _commandServer->replyQName());
		_mqwebData->set("cmdq", _commandServer->commandQName());
	}
}

void MQController::handleException(const MQException& mqe)
{
	Poco::JSON::Object::Ptr error = new Poco::JSON::Object();

	set("error", error);
	error->set("object", mqe.object());
	error->set("fn", mqe.function());
	switch(mqe.code())
	{
		case MQCC_OK: error->set("code", "OK"); break;
		case MQCC_WARNING: error->set("code", "WARNING"); break;
		case MQCC_FAILED: error->set("code", "ERROR"); break;
	}

	Poco::JSON::Object::Ptr reason = new Poco::JSON::Object();
	error->set("reason", reason);
	reason->set("code", mqe.reason());
	reason->set("desc", MQMapper::getReasonString(mqe.reason()));

	if ( isJSON() )
	{
		setJSONView();
	}
	else
	{
		setView(new TemplateView("error.tpl"));
	}
}

void MQController::afterAction()
{
	Poco::JSON::Object::Ptr date = _mqwebData->getObject("date");
	if ( ! date.isNull() )
	{
		date->set("end", Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT));
	}

	_stopwatch.stop();
	_mqwebData->set("elapsed", (double) _stopwatch.elapsed() / 1000000 );

	Controller::afterAction();
}

void MQController::handle(const std::vector<std::string>& parameters, Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
	try
	{
		Controller::handle(parameters, request, response);
	}
	catch(MQException& mqe)
	{
		handleException(mqe);
		afterAction();
	}
	catch(...)
	{
		//TODO: redirect to an error page
	}
}

void MQController::handleFilterForm(Poco::JSON::Object::Ptr pcfParameters)
{
	if ( form().has("Filter") && form().has("FilterParam") && form().has("FilterValue") )
	{
		Poco::JSON::Object::Ptr filter = new Poco::JSON::Object();
		filter->set("Parameter", form().get("FilterParam"));
		filter->set("Operator", form().get("FilterOp", "EQ"));
		filter->set("FilterValue", form().get("FilterVlue"));

		std::string filterType = form().get("Filter");
		if ( Poco::icompare(filterType, "I") == 0 )
		{
			pcfParameters->set("IntegerFilterCommand", filter);
		}
		else if ( Poco::icompare(filterType, "S") == 0 )
		{
			pcfParameters->set("StringFilterCommand", filter);
		}
	}
}

}} // namespace MQ::Web
<commit_msg>Set HTTP status when no pool for queuemanagers is available or when there is no queuemanager available ...<commit_after>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include "Poco/Util/Application.h"
#include "Poco/Dynamic/Struct.h"
#include "Poco/JSON/Object.h"

#include "MQ/MQSubsystem.h"
#include "MQ/MQException.h"

#include "MQ/Web/MQController.h"
#include "MQ/Web/MQMapper.h"
#include "MQ/Web/TemplateView.h"
#include "MQ/Web/JSONView.h"

namespace MQ {
namespace Web {

MQController::MQController() : Controller(), _mqwebData(new Poco::JSON::Object()), _commandServer(NULL)
{
	set("mqweb", _mqwebData);
}

MQController::~MQController()
{
}

void MQController::beforeAction()
{
	_stopwatch.start();

	Poco::JSON::Object::Ptr date = new Poco::JSON::Object();
	_mqwebData->set("date", date);
	date->set("start", Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT));

	MQSubsystem& mqSystem = Poco::Util::Application::instance().getSubsystem<MQSubsystem>();
	Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();

	_mqwebData->set("client", mqSystem.client());

	std::string qmgrName;
	if ( config.hasProperty("mq.web.qmgr") )
	{
		// When a queuemanager is passed on the command line, we always
		// connect to this queuemanager. When the user specified another
		// queuemanager on the URL, it will be ignored.
		qmgrName = config.getString("mq.web.qmgr");
	}
	else
	{
		const std::vector<std::string>& parameters = getParameters();
		if ( parameters.size() > 0 )
		{
			qmgrName = parameters[0];
		}
		else if ( mqSystem.client() )
		{
			qmgrName = config.getString("mq.web.defaultQmgr", "*");
		}
	}

	Poco::SharedPtr<QueueManagerPool> qmgrPool = QueueManagerPoolCache::instance()->getQueueManagerPool(qmgrName);
	if ( qmgrPool.isNull() )
	{
		setResponseStatus(Poco::Net::HTTPServerResponse::HTTP_INTERNAL_SERVER_ERROR, "Out of memory: can't create a pool for queuemanager.");
		return;
	}

	QueueManager::Ptr qmgr = qmgrPool->borrowObject();
	if ( qmgr.isNull() )
	{
		setResponseStatus(Poco::Net::HTTPServerResponse::HTTP_INTERNAL_SERVER_ERROR, "No queuemanager available in the pool. Check the connection pool configuration.");
		return;
	}
	_qmgrPoolGuard = new QueueManagerPoolGuard(qmgrPool, qmgr);

	_mqwebData->set("qmgr", qmgr->name());
	_mqwebData->set("zos", qmgr->zos());
	_mqwebData->set("qmgrId", qmgr->id());

	_commandServer = qmgr->commandServer();
	if ( _commandServer == NULL )
	{
		std::string qmgrConfigReplyQ = "mq.web.qmgr." + qmgrName + ".reply";

		std::string replyQ;
		if ( config.has(qmgrConfigReplyQ) )
		{
			replyQ = config.getString(qmgrConfigReplyQ);
		}
		else
		{
			replyQ = config.getString("mq.web.reply", "SYSTEM.DEFAULT.MODEL.QUEUE");
		}
		_commandServer = qmgr->createCommandServer(replyQ);
	}

	if ( _commandServer != NULL )
	{
		_mqwebData->set("replyq", _commandServer->replyQName());
		_mqwebData->set("cmdq", _commandServer->commandQName());
	}
}

void MQController::handleException(const MQException& mqe)
{
	Poco::JSON::Object::Ptr error = new Poco::JSON::Object();

	set("error", error);
	error->set("object", mqe.object());
	error->set("fn", mqe.function());
	switch(mqe.code())
	{
		case MQCC_OK: error->set("code", "OK"); break;
		case MQCC_WARNING: error->set("code", "WARNING"); break;
		case MQCC_FAILED: error->set("code", "ERROR"); break;
	}

	Poco::JSON::Object::Ptr reason = new Poco::JSON::Object();
	error->set("reason", reason);
	reason->set("code", mqe.reason());
	reason->set("desc", MQMapper::getReasonString(mqe.reason()));

	if ( isJSON() )
	{
		setJSONView();
	}
	else
	{
		setView(new TemplateView("error.tpl"));
	}
}

void MQController::afterAction()
{
	Poco::JSON::Object::Ptr date = _mqwebData->getObject("date");
	if ( ! date.isNull() )
	{
		date->set("end", Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT));
	}

	_stopwatch.stop();
	_mqwebData->set("elapsed", (double) _stopwatch.elapsed() / 1000000 );

	Controller::afterAction();
}

void MQController::handle(const std::vector<std::string>& parameters, Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
	try
	{
		Controller::handle(parameters, request, response);
	}
	catch(MQException& mqe)
	{
		handleException(mqe);
		afterAction();
	}
	catch(...)
	{
		//TODO: redirect to an error page
	}
}

void MQController::handleFilterForm(Poco::JSON::Object::Ptr pcfParameters)
{
	if ( form().has("Filter") && form().has("FilterParam") && form().has("FilterValue") )
	{
		Poco::JSON::Object::Ptr filter = new Poco::JSON::Object();
		filter->set("Parameter", form().get("FilterParam"));
		filter->set("Operator", form().get("FilterOp", "EQ"));
		filter->set("FilterValue", form().get("FilterVlue"));

		std::string filterType = form().get("Filter");
		if ( Poco::icompare(filterType, "I") == 0 )
		{
			pcfParameters->set("IntegerFilterCommand", filter);
		}
		else if ( Poco::icompare(filterType, "S") == 0 )
		{
			pcfParameters->set("StringFilterCommand", filter);
		}
	}
}

}} // namespace MQ::Web
<|endoftext|>


<commit_before>#include "Units.h"
#include "Planar.h"
using namespace GeFiCa;

Planar::Planar(const char *name, const char *title)
   : Detector(name,title), Width(1*cm), Depth(1*cm) {};
<commit_msg>added a bias voltage<commit_after>#include "Units.h"
#include "Planar.h"
using namespace GeFiCa;

Planar::Planar(const char *name, const char *title)
   : Detector(name,title), Width(1*cm), Depth(1*cm)
{ Bias.push_back(1*kV); }
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (C) 2008-2016 Ryo Suzuki
//	Copyright (C) 2016 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include "../../ThirdParty/zstd/zstd.h"
# include <Siv3D/Compression.hpp>
# include <Siv3D/BinaryReader.hpp>
# include <Siv3D/BinaryWriter.hpp>

namespace s3d
{
	namespace Compression
	{
		ByteArray Compress(const ByteArrayView view, const int32 compressionLevel)
		{
			const size_t bufferSize = ZSTD_compressBound(view.size());

			Array<uint8> buffer(bufferSize);

			const size_t result = ZSTD_compress(buffer.data(), buffer.size(), view.data(), view.size(), compressionLevel);

			if (ZSTD_isError(result))
			{
				return ByteArray();
			}

			buffer.resize(result);

			buffer.shrink_to_fit();

			return ByteArray(std::move(buffer));
		}

		ByteArray CompressFile(const FilePath& path, const int32 compressionLevel)
		{
			BinaryReader reader(path);

			if (!reader)
			{
				return ByteArray();
			}

			const size_t inputBufferSize = ZSTD_CStreamInSize();
			const auto pInputBuffer = std::make_unique<uint8[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_CStreamOutSize();
			const auto pOutputBuffer = std::make_unique<uint8[]>(outputBufferSize);

			ZSTD_CStream* const cStream = ZSTD_createCStream();

			if (!cStream)
			{
				return ByteArray();
			}

			const size_t initResult = ZSTD_initCStream(cStream, compressionLevel);

			if (ZSTD_isError(initResult))
			{
				return ByteArray();
			}

			size_t toRead = inputBufferSize;

			Array<uint8> buffer;

			while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead)))
			{
				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_compressStream(cStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						return ByteArray();
					}

					if (toRead > inputBufferSize)
					{
						toRead = inputBufferSize;
					}

					buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos);
				}
			}

			ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

			const size_t remainingToFlush = ZSTD_endStream(cStream, &output);

			if (remainingToFlush)
			{
				return ByteArray();
			}

			buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos);

			return ByteArray(std::move(buffer));
		}

		bool CompressToFile(const ByteArrayView view, const FilePath& outputPath, const int32 compressionLevel)
		{
			const size_t inputBufferSize = ZSTD_CStreamInSize();
			const auto pInputBuffer = std::make_unique<uint8[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_CStreamOutSize();
			const auto pOutputBuffer = std::make_unique<uint8[]>(outputBufferSize);

			ZSTD_CStream* const cStream = ZSTD_createCStream();

			if (!cStream)
			{
				return false;
			}

			const size_t initResult = ZSTD_initCStream(cStream, compressionLevel);

			if (ZSTD_isError(initResult))
			{
				return false;
			}

			size_t toRead = inputBufferSize;

			BinaryWriter writer(outputPath);

			if (!writer)
			{
				return false;
			}

			size_t readPos = 0;

			for (;;)
			{
				const size_t read = std::min(toRead, view.size() - readPos);

				if (read == 0)
				{
					break;
				}

				::memcpy(pInputBuffer.get(), view.data() + readPos, read);

				readPos += read;

				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_compressStream(cStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						writer.clear();

						return false;
					}

					if (toRead > inputBufferSize)
					{
						toRead = inputBufferSize;
					}

					writer.write(pOutputBuffer.get(), output.pos);
				}
			}

			ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

			const size_t remainingToFlush = ZSTD_endStream(cStream, &output);

			if (remainingToFlush)
			{
				writer.clear();

				return false;
			}

			writer.write(pOutputBuffer.get(), output.pos);

			return true;
		}

		bool CompressFileToFile(const FilePath& inputPath, const FilePath& outputPath, const int32 compressionLevel)
		{
			BinaryReader reader(inputPath);

			if (!reader)
			{
				return false;
			}

			const size_t inputBufferSize = ZSTD_CStreamInSize();
			const auto pInputBuffer = std::make_unique<uint8[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_CStreamOutSize();
			const auto pOutputBuffer = std::make_unique<uint8[]>(outputBufferSize);

			ZSTD_CStream* const cStream = ZSTD_createCStream();

			if (!cStream)
			{
				return false;
			}

			const size_t initResult = ZSTD_initCStream(cStream, compressionLevel);

			if (ZSTD_isError(initResult))
			{
				return false;
			}

			size_t toRead = inputBufferSize;

			BinaryWriter writer(outputPath);

			if (!writer)
			{
				return false;
			}

			while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead)))
			{
				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_compressStream(cStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						writer.clear();

						return false;
					}

					if (toRead > inputBufferSize)
					{
						toRead = inputBufferSize;
					}

					writer.write(pOutputBuffer.get(), output.pos);
				}
			}

			ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

			const size_t remainingToFlush = ZSTD_endStream(cStream, &output);

			if (remainingToFlush)
			{
				writer.clear();

				return false;
			}

			writer.write(pOutputBuffer.get(), output.pos);

			return true;
		}

		ByteArray Decompress(const ByteArrayView view)
		{
			const uint64 originalSize = ZSTD_getDecompressedSize(view.data(), view.size());

			if (originalSize == 0)
			{
				return ByteArray();
			}

			Array<uint8> outputBuffer(static_cast<size_t>(originalSize));

			const size_t decompressedSize = ZSTD_decompress(outputBuffer.data(), outputBuffer.size(), view.data(), view.size());

			if (originalSize != decompressedSize)
			{
				return ByteArray();
			}

			return ByteArray(std::move(outputBuffer));
		}
	}
}
<commit_msg>DecompressFileToFile<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (C) 2008-2016 Ryo Suzuki
//	Copyright (C) 2016 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include "../../ThirdParty/zstd/zstd.h"
# include <Siv3D/Compression.hpp>
# include <Siv3D/BinaryReader.hpp>
# include <Siv3D/BinaryWriter.hpp>

namespace s3d
{
	namespace Compression
	{
		ByteArray Compress(const ByteArrayView view, const int32 compressionLevel)
		{
			const size_t bufferSize = ZSTD_compressBound(view.size());

			Array<uint8> buffer(bufferSize);

			const size_t result = ZSTD_compress(buffer.data(), buffer.size(), view.data(), view.size(), compressionLevel);

			if (ZSTD_isError(result))
			{
				return ByteArray();
			}

			buffer.resize(result);

			buffer.shrink_to_fit();

			return ByteArray(std::move(buffer));
		}

		ByteArray CompressFile(const FilePath& path, const int32 compressionLevel)
		{
			BinaryReader reader(path);

			if (!reader)
			{
				return ByteArray();
			}

			const size_t inputBufferSize = ZSTD_CStreamInSize();
			const auto pInputBuffer = std::make_unique<uint8[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_CStreamOutSize();
			const auto pOutputBuffer = std::make_unique<uint8[]>(outputBufferSize);

			ZSTD_CStream* const cStream = ZSTD_createCStream();

			if (!cStream)
			{
				return ByteArray();
			}

			const size_t initResult = ZSTD_initCStream(cStream, compressionLevel);

			if (ZSTD_isError(initResult))
			{
				return ByteArray();
			}

			size_t toRead = inputBufferSize;

			Array<uint8> buffer;

			while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead)))
			{
				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_compressStream(cStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						return ByteArray();
					}

					if (toRead > inputBufferSize)
					{
						toRead = inputBufferSize;
					}

					buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos);
				}
			}

			ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

			const size_t remainingToFlush = ZSTD_endStream(cStream, &output);

			if (remainingToFlush)
			{
				return ByteArray();
			}

			buffer.insert(buffer.end(), pOutputBuffer.get(), pOutputBuffer.get() + output.pos);

			return ByteArray(std::move(buffer));
		}

		bool CompressToFile(const ByteArrayView view, const FilePath& outputPath, const int32 compressionLevel)
		{
			const size_t inputBufferSize = ZSTD_CStreamInSize();
			const auto pInputBuffer = std::make_unique<uint8[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_CStreamOutSize();
			const auto pOutputBuffer = std::make_unique<uint8[]>(outputBufferSize);

			ZSTD_CStream* const cStream = ZSTD_createCStream();

			if (!cStream)
			{
				return false;
			}

			const size_t initResult = ZSTD_initCStream(cStream, compressionLevel);

			if (ZSTD_isError(initResult))
			{
				return false;
			}

			size_t toRead = inputBufferSize;

			BinaryWriter writer(outputPath);

			if (!writer)
			{
				return false;
			}

			size_t readPos = 0;

			for (;;)
			{
				const size_t read = std::min(toRead, view.size() - readPos);

				if (read == 0)
				{
					break;
				}

				::memcpy(pInputBuffer.get(), view.data() + readPos, read);

				readPos += read;

				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_compressStream(cStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						writer.clear();

						return false;
					}

					if (toRead > inputBufferSize)
					{
						toRead = inputBufferSize;
					}

					writer.write(pOutputBuffer.get(), output.pos);
				}
			}

			ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

			const size_t remainingToFlush = ZSTD_endStream(cStream, &output);

			if (remainingToFlush)
			{
				writer.clear();

				return false;
			}

			writer.write(pOutputBuffer.get(), output.pos);

			return true;
		}

		bool CompressFileToFile(const FilePath& inputPath, const FilePath& outputPath, const int32 compressionLevel)
		{
			BinaryReader reader(inputPath);

			if (!reader)
			{
				return false;
			}

			const size_t inputBufferSize = ZSTD_CStreamInSize();
			const auto pInputBuffer = std::make_unique<uint8[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_CStreamOutSize();
			const auto pOutputBuffer = std::make_unique<uint8[]>(outputBufferSize);

			ZSTD_CStream* const cStream = ZSTD_createCStream();

			if (!cStream)
			{
				return false;
			}

			const size_t initResult = ZSTD_initCStream(cStream, compressionLevel);

			if (ZSTD_isError(initResult))
			{
				return false;
			}

			size_t toRead = inputBufferSize;

			BinaryWriter writer(outputPath);

			if (!writer)
			{
				return false;
			}

			while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead)))
			{
				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_compressStream(cStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						writer.clear();

						return false;
					}

					if (toRead > inputBufferSize)
					{
						toRead = inputBufferSize;
					}

					writer.write(pOutputBuffer.get(), output.pos);
				}
			}

			ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

			const size_t remainingToFlush = ZSTD_endStream(cStream, &output);

			if (remainingToFlush)
			{
				writer.clear();

				return false;
			}

			writer.write(pOutputBuffer.get(), output.pos);

			return true;
		}

		ByteArray Decompress(const ByteArrayView view)
		{
			const uint64 originalSize = ZSTD_getDecompressedSize(view.data(), view.size());

			if (originalSize == 0)
			{
				return ByteArray();
			}

			Array<uint8> outputBuffer(static_cast<size_t>(originalSize));

			const size_t decompressedSize = ZSTD_decompress(outputBuffer.data(), outputBuffer.size(), view.data(), view.size());

			if (originalSize != decompressedSize)
			{
				return ByteArray();
			}

			return ByteArray(std::move(outputBuffer));
		}

		//ByteArray DecompressFile(const FilePath& path);

		//bool DecompressToFile(const ByteArrayView view, const FilePath& outputPath);

		bool DecompressFileToFile(const FilePath& inputPath, const FilePath& outputPath)
		{
			BinaryReader reader(inputPath);

			if (!reader)
			{
				return false;
			}

			const size_t inputBufferSize = ZSTD_DStreamInSize();
			const auto pInputBuffer = std::make_unique<uint8[]>(inputBufferSize);

			const size_t outputBufferSize = ZSTD_DStreamOutSize();
			const auto pOutputBuffer = std::make_unique<uint8[]>(outputBufferSize);

			ZSTD_DStream* const dStream = ZSTD_createDStream();

			if (!dStream)
			{
				return false;
			}

			const size_t initResult = ZSTD_initDStream(dStream);

			if (ZSTD_isError(initResult))
			{
				return false;
			}

			size_t toRead = initResult;

			BinaryWriter writer(outputPath);

			if (!writer)
			{
				return false;
			}

			while (const size_t read = static_cast<size_t>(reader.read(pInputBuffer.get(), toRead)))
			{
				ZSTD_inBuffer input = { pInputBuffer.get(), read, 0 };

				while (input.pos < input.size)
				{
					ZSTD_outBuffer output = { pOutputBuffer.get(), outputBufferSize, 0 };

					toRead = ZSTD_decompressStream(dStream, &output, &input);

					if (ZSTD_isError(toRead))
					{
						writer.clear();

						return false;
					}

					writer.write(pOutputBuffer.get(), output.pos);
				}
			}

			ZSTD_freeDStream(dStream);
		}
	}
}
<|endoftext|>


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

  Program:   Visualization Library
  Module:    PtLoad.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "PtLoad.hh"
#include "vtkMath.hh"
#include "FTensors.hh"

// Description:
// Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50),
// and LoadValue = 1.
vtkPointLoad::vtkPointLoad()
{
 this->LoadValue = 1.0;

  this->ModelBounds[0] = -1.0;
  this->ModelBounds[1] = 1.0;
  this->ModelBounds[2] = -1.0;
  this->ModelBounds[3] = 1.0;
  this->ModelBounds[4] = -1.0;
  this->ModelBounds[5] = 1.0;

  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;
}

// Description:
// Specify the dimensions of the volume. A stress tensor will be computed for
// each point in the volume.
void vtkPointLoad::SetSampleDimensions(int i, int j, int k)
{
  int dim[3];

  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
}

// Description:
// Specify the dimensions of the volume. A stress tensor will be computed for
// each point in the volume.
void vtkPointLoad::SetSampleDimensions(int dim[3])
{
  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");

  if ( dim[0] != this->SampleDimensions[0] || dim[1] != SampleDimensions[1] ||
  dim[2] != SampleDimensions[2] )
    {
    for ( int i=0; i<3; i++)
      this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1);
    this->Modified();
    }
}

// Description:
// Specify the region in space over which the tensors are computed. The point
// load is assumed to be applied at top center of the volume.
void vtkPointLoad::SetModelBounds(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
{
  if (this->ModelBounds[0] != xmin || this->ModelBounds[1] != xmax ||
  this->ModelBounds[2] != ymin || this->ModelBounds[3] != ymax ||
  this->ModelBounds[4] != zmin || this->ModelBounds[5] != zmax )
    {
    this->Modified();
    this->ModelBounds[0] = xmin;
    this->ModelBounds[1] = xmax;
    this->ModelBounds[2] = ymin;
    this->ModelBounds[3] = ymax;
    this->ModelBounds[4] = zmin;
    this->ModelBounds[5] = zmax;
    }
}

// Description:
// Specify the region in space over which the tensors are computed. The point
// load is assumed to be applied at top center of the volume.
void vtkPointLoad::SetModelBounds(float *bounds)
{
  vtkPointLoad::SetModelBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
}

void vtkPointLoad::Execute()
{
  int ptId, i, j, k;
  vtkFloatTensors *newTensors;
  vtkTensor tensor;
  int numPts;
  vtkMath math;
  float P, pi, twoPi, xP[3], rho, rho2, rho3, rho5, nu;
  float x, x2, y, y2, z, z2, z3, rhoPlusz2, zPlus2rho, txy, txz, tyz;

  vtkDebugMacro(<< "Computing point load stress tensors");
//
// Initialize self; create output objects
//
  this->Initialize();

  numPts = this->SampleDimensions[0] * this->SampleDimensions[1]
           * this->SampleDimensions[2];
  newTensors = new vtkFloatTensors(numPts);

  // Compute origin and aspect ratio
  this->SetDimensions(this->GetSampleDimensions());
  for (i=0; i < 3; i++)
    {
    this->Origin[i] = this->ModelBounds[2*i];
    this->AspectRatio[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
                           / (this->SampleDimensions[i] - 1);
    }
//
// Compute the location of the load
//
  xP[0] = (this->ModelBounds[0] + this->ModelBounds[1]) / 2.0; //in center
  xP[1] = (this->ModelBounds[2] + this->ModelBounds[3]) / 2.0;
  xP[2] = this->ModelBounds[5]; // at top of box
//
// Traverse all points evaluating implicit function at each point
//
  twoPi = 2.0*math.Pi();
  P = -this->LoadValue;

  for (k=0; k<this->Dimensions[2]; k++)
    {
    z = this->Origin[2] + k*this->AspectRatio[2];
    for (j=0; j<this->Dimensions[1]; j++)
      {
      y = this->Origin[1] + k*this->AspectRatio[1];
      for (i=0; i<this->Dimensions[0]; i++)
        {
        x = this->Origin[0] + k*this->AspectRatio[0];
        rho = sqrt((x-xP[0])*(x-xP[0]) + (y-xP[1])*(y-xP[1]) +
                   (z-xP[2])*(z-xP[2]));
        rho2 = rho*rho;
        rho3 = rho2*rho;
        rho5 = rho2*rho3;
        nu = (1.0 - 2.0*this->PoissonsRatio);
        x2 = x*x;
        y2 = y*y;
        rhoPlusz2 = (rho + z) * (rho + z);
        zPlus2rho = (2.0*rho + z);

        // normal stresses
        tensor.SetComponent(0,0, P/(twoPi*rho2) * (3.0*z*x2/rho3 -
                     nu*(z/rho - rho/(rho+z) + x2*(zPlus2rho)/(rho*rhoPlusz2))));
        tensor.SetComponent(1,1, P/(twoPi*rho2) * (3.0*z*y2/rho3 -
                     nu*(z/rho - rho/(rho+z) + y2*(zPlus2rho)/(rho*rhoPlusz2))));
        tensor.SetComponent(2,2, 3.0*P*z3/(twoPi*rho5));

        //shear stresses
        txy = P/(twoPi*rho2) * (3.0*x*y*z/rho3 -
                                nu*x*y*(zPlus2rho)/(rho*rhoPlusz2));

        tensor.SetComponent(0,1,txy);
        tensor.SetComponent(1,0,txy);

        txz = 3.0*P*x*z2/(twoPi*rho5);
        tensor.SetComponent(0,2,txz);
        tensor.SetComponent(2,0,txz);

        tyz = 3.0*P*y*z2/(twoPi*rho5);
        tensor.SetComponent(1,2,tyz);
        tensor.SetComponent(2,1,tyz);

        newTensors->InsertNextTensor(tensor);
        }
      }
    }
//
// Update self
//
  this->PointData.SetTensors(newTensors);
}

void vtkPointLoad::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsSource::PrintSelf(os,indent);

  os << indent << "Load Value: " << this->LoadValue << "\n";
  os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
               << this->SampleDimensions[1] << ", "
               << this->SampleDimensions[2] << ")\n";
  os << indent << "ModelBounds: \n";
  os << indent << "  Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n";
  os << indent << "  Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n";
  os << indent << "  Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n";
  os << indent << "Poisson's Ratio: " << this->PoissonsRatio << "\n";

}

<commit_msg>ENH: Code around singularity.<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    PtLoad.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "PtLoad.hh"
#include "vtkMath.hh"
#include "FTensors.hh"

// Description:
// Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50),
// and LoadValue = 1.
vtkPointLoad::vtkPointLoad()
{
 this->LoadValue = 1.0;

  this->ModelBounds[0] = -1.0;
  this->ModelBounds[1] = 1.0;
  this->ModelBounds[2] = -1.0;
  this->ModelBounds[3] = 1.0;
  this->ModelBounds[4] = -1.0;
  this->ModelBounds[5] = 1.0;

  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;
}

// Description:
// Specify the dimensions of the volume. A stress tensor will be computed for
// each point in the volume.
void vtkPointLoad::SetSampleDimensions(int i, int j, int k)
{
  int dim[3];

  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
}

// Description:
// Specify the dimensions of the volume. A stress tensor will be computed for
// each point in the volume.
void vtkPointLoad::SetSampleDimensions(int dim[3])
{
  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");

  if ( dim[0] != this->SampleDimensions[0] || dim[1] != SampleDimensions[1] ||
  dim[2] != SampleDimensions[2] )
    {
    for ( int i=0; i<3; i++)
      this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1);
    this->Modified();
    }
}

// Description:
// Specify the region in space over which the tensors are computed. The point
// load is assumed to be applied at top center of the volume.
void vtkPointLoad::SetModelBounds(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
{
  if (this->ModelBounds[0] != xmin || this->ModelBounds[1] != xmax ||
  this->ModelBounds[2] != ymin || this->ModelBounds[3] != ymax ||
  this->ModelBounds[4] != zmin || this->ModelBounds[5] != zmax )
    {
    this->Modified();
    this->ModelBounds[0] = xmin;
    this->ModelBounds[1] = xmax;
    this->ModelBounds[2] = ymin;
    this->ModelBounds[3] = ymax;
    this->ModelBounds[4] = zmin;
    this->ModelBounds[5] = zmax;
    }
}

// Description:
// Specify the region in space over which the tensors are computed. The point
// load is assumed to be applied at top center of the volume.
void vtkPointLoad::SetModelBounds(float *bounds)
{
  vtkPointLoad::SetModelBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
}

void vtkPointLoad::Execute()
{
  int ptId, i, j, k;
  vtkFloatTensors *newTensors;
  vtkTensor tensor;
  int numPts;
  vtkMath math;
  float P, pi, twoPi, xP[3], rho, rho2, rho3, rho5, nu;
  float x, x2, y, y2, z, z2, z3, rhoPlusz2, zPlus2rho, txy, txz, tyz;

  vtkDebugMacro(<< "Computing point load stress tensors");
//
// Initialize self; create output objects
//
  this->Initialize();

  numPts = this->SampleDimensions[0] * this->SampleDimensions[1]
           * this->SampleDimensions[2];
  newTensors = new vtkFloatTensors(numPts);

  // Compute origin and aspect ratio
  this->SetDimensions(this->GetSampleDimensions());
  for (i=0; i < 3; i++)
    {
    this->Origin[i] = this->ModelBounds[2*i];
    this->AspectRatio[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
                           / (this->SampleDimensions[i] - 1);
    }
//
// Compute the location of the load
//
  xP[0] = (this->ModelBounds[0] + this->ModelBounds[1]) / 2.0; //in center
  xP[1] = (this->ModelBounds[2] + this->ModelBounds[3]) / 2.0;
  xP[2] = this->ModelBounds[5]; // at top of box
//
// Traverse all points evaluating implicit function at each point
//
  twoPi = 2.0*math.Pi();
  P = -this->LoadValue;

  for (k=0; k<this->Dimensions[2]; k++)
    {
    z = this->Origin[2] + k*this->AspectRatio[2];
    for (j=0; j<this->Dimensions[1]; j++)
      {
      y = this->Origin[1] + k*this->AspectRatio[1];
      for (i=0; i<this->Dimensions[0]; i++)
        {
        x = this->Origin[0] + k*this->AspectRatio[0];
        rho = sqrt((x-xP[0])*(x-xP[0]) + (y-xP[1])*(y-xP[1]) +
                   (z-xP[2])*(z-xP[2]));
        if ( rho < 1.0e-10 )
          {
          vtkWarningMacro(<<"Attempting to set singularity, resetting");
          tensor.SetComponent(0,0,LARGE_FLOAT);
          tensor.SetComponent(1,1,LARGE_FLOAT);
          tensor.SetComponent(2,2,LARGE_FLOAT);
          tensor.SetComponent(0,1,0.0);
          tensor.SetComponent(0,2,0.0);
          tensor.SetComponent(1,0,0.0);
          tensor.SetComponent(1,2,0.0);
          tensor.SetComponent(2,0,0.0);
          tensor.SetComponent(2,1,0.0);
          newTensors->InsertNextTensor(tensor);
          continue;
          }

        rho2 = rho*rho;
        rho3 = rho2*rho;
        rho5 = rho2*rho3;
        nu = (1.0 - 2.0*this->PoissonsRatio);
        x2 = x*x;
        y2 = y*y;
        rhoPlusz2 = (rho + z) * (rho + z);
        zPlus2rho = (2.0*rho + z);

        // normal stresses
        tensor.SetComponent(0,0, P/(twoPi*rho2) * (3.0*z*x2/rho3 -
                     nu*(z/rho - rho/(rho+z) + x2*(zPlus2rho)/(rho*rhoPlusz2))));
        tensor.SetComponent(1,1, P/(twoPi*rho2) * (3.0*z*y2/rho3 -
                     nu*(z/rho - rho/(rho+z) + y2*(zPlus2rho)/(rho*rhoPlusz2))));
        tensor.SetComponent(2,2, 3.0*P*z3/(twoPi*rho5));

        //shear stresses
        txy = P/(twoPi*rho2) * (3.0*x*y*z/rho3 -
                                nu*x*y*(zPlus2rho)/(rho*rhoPlusz2));

        tensor.SetComponent(0,1,txy);
        tensor.SetComponent(1,0,txy);

        txz = 3.0*P*x*z2/(twoPi*rho5);
        tensor.SetComponent(0,2,txz);
        tensor.SetComponent(2,0,txz);

        tyz = 3.0*P*y*z2/(twoPi*rho5);
        tensor.SetComponent(1,2,tyz);
        tensor.SetComponent(2,1,tyz);

        newTensors->InsertNextTensor(tensor);
        }
      }
    }
//
// Update self
//
  this->PointData.SetTensors(newTensors);
}

void vtkPointLoad::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsSource::PrintSelf(os,indent);

  os << indent << "Load Value: " << this->LoadValue << "\n";
  os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
               << this->SampleDimensions[1] << ", "
               << this->SampleDimensions[2] << ")\n";
  os << indent << "ModelBounds: \n";
  os << indent << "  Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n";
  os << indent << "  Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n";
  os << indent << "  Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n";
  os << indent << "Poisson's Ratio: " << this->PoissonsRatio << "\n";

}

<|endoftext|>


<commit_before>/*
 * LoopSubdivsionivision.cpp
 *
 *  Created on: Sep 3, 2013
 *      Author: schurade
 */

#include "loopsubdivision.h"

#include "../data/mesh/trianglemesh2.h"

#include <QDebug>

LoopSubdivision::~LoopSubdivision()
{
}

LoopSubdivision::LoopSubdivision( TriangleMesh2* mesh ) :
    m_mesh( mesh )
{
    m_mesh = new TriangleMesh2( mesh );

    m_numVerts = m_mesh->numVerts();
    m_numTris = m_mesh->numTris();

    qDebug() << m_numVerts << m_numTris;

    m_mesh->resize( m_numVerts * 4, m_numTris * 4 );

    QVector<QVector3D> newVertexPositions( m_numVerts );

    for ( int i = 0; i < m_numVerts; ++i )
    {
        newVertexPositions[i] = calcNewPosition( i );
    }

    //printf("loop subdivision pass 2\n");
    for ( int i = 0; i < m_numTris; ++i )
    {
        insertCenterTriangle( i );
    }

    //printf("loop subdivision pass 3\n");
    for ( int i = 0; i < m_numTris; ++i )
    {
        insertCornerTriangles( i );
    }

    //printf("loop subdivision pass 4\n");
    for ( int i = 0; i < m_numVerts; ++i )
    {
        m_mesh->addVertex( i, newVertexPositions[i] );
    }

    m_numVerts = m_mesh->numVerts();
    m_numTris = m_mesh->numTris();

    qDebug() << m_numVerts << m_numTris;

    m_mesh->finalize();

    newVertexPositions.clear();
    newVertexPositions.squeeze();

}

QVector3D LoopSubdivision::calcNewPosition( int vertNum )
{
    QVector<int> starP = m_mesh->getStar( vertNum );
    int starSize = starP.size();

    QVector3D oldPos = m_mesh->getVertex( vertNum );
    double alpha = getAlpha( starSize );
    oldPos *= ( 1.0 - ( (double) starSize * alpha ) );

    QVector3D newPos;
    int edgeV = 0;
    for ( int i = 0; i < starSize; i++ )
    {
        edgeV = m_mesh->getNextVertex( starP[i], vertNum );
        newPos += m_mesh->getVertex( edgeV );
    }
    newPos *= alpha;

    return oldPos + newPos;
}

void LoopSubdivision::insertCenterTriangle( int triNum )
{

    QVector<int> intP = m_mesh->getTriangle( triNum );
    int edgeVerts[3];

    for ( int i = 0; i < 3; ++i )
    {
        edgeVerts[i] = calcEdgeVert( triNum, intP[i], intP[( i + 1 ) % 3], intP[( i + 2 ) % 3] );
    }
    m_mesh->addTriangle( edgeVerts[0], edgeVerts[1], edgeVerts[2] );
}

void LoopSubdivision::insertCornerTriangles( int triNum )
{

    // comment:     center are twisted from the orignal vertices.
    // original:    0, 1, 2
    // center:      a, b, c
    // reAsgnOrig:  0, a, c
    // addTris:     1, b, a
    // addTris:     2, c, b
    //
    QVector<int> originalTri = m_mesh->getTriangle( triNum );
    QVector<int> centerTri = m_mesh->getTriangle( triNum + m_numTris );

    m_mesh->addTriangle( originalTri[1], centerTri[1], centerTri[0] );
    m_mesh->addTriangle( originalTri[2], centerTri[2], centerTri[1] );
    m_mesh->addTriangle( triNum, originalTri[0], centerTri[0], centerTri[2] );
}

int LoopSubdivision::calcEdgeVert( int triNum, int edgeV1, int edgeV2, int V3 )
{

    int vertNum = -1;

    int neighborVert = -1;
    int neighborFaceNum = -1;
    QVector3D edgeVert;

    neighborFaceNum = m_mesh->getNeighbor( edgeV1, edgeV2, triNum );

    if ( neighborFaceNum == triNum )
    {
        QVector3D edgeVert = ( m_mesh->getVertex( edgeV1 ) + m_mesh->getVertex( edgeV2 ) ) / 2.0;
        vertNum = m_mesh->currentNumVerts();
        m_mesh->addVertex( edgeVert.x(), edgeVert.y(), edgeVert.z() );
    }

    else if ( neighborFaceNum > triNum )
    {
        QVector<int> tri = m_mesh->getTriangle( neighborFaceNum );

        if ( tri[0] == edgeV1 || tri[0] == edgeV2 )
        {
            if ( tri[1] == edgeV1 || tri[1] == edgeV2 )
            {
                neighborVert = tri[2];
            }
            else
            {
                neighborVert = tri[1];
            }
        }
        else
        {
            neighborVert = tri[0];
        }

        QVector3D edgePart = m_mesh->getVertex( edgeV1 ) + m_mesh->getVertex( edgeV2 );
        QVector3D neighborPart = m_mesh->getVertex( neighborVert ) + m_mesh->getVertex( V3 );

        edgeVert = ( ( edgePart * ( 3.0 / 8.0 ) ) + ( neighborPart * ( 1.0 / 8.0 ) ) );
        vertNum = m_mesh->currentNumVerts();
        m_mesh->addVertex( edgeVert.x(), edgeVert.y(), edgeVert.z() );
    }
    else
    {
        QVector<int> neighborCenterP = m_mesh->getTriangle( neighborFaceNum + m_numTris );
        QVector<int> neighborP = m_mesh->getTriangle( neighborFaceNum );

        if ( neighborP[0] == edgeV2 )
        {
            vertNum = neighborCenterP[0];
        }
        else if ( neighborP[1] == edgeV2 )
        {
            vertNum = neighborCenterP[1];
        }
        else
        {
            vertNum = neighborCenterP[2];
        }
    }
    return vertNum;
}

double LoopSubdivision::getAlpha( int n )
{
    double answer;
    if ( n > 3 )
    {
        double center = ( 0.375 + ( 0.25 * cos( ( 2.0 * 3.14159265358979 ) / (double) n ) ) );
        answer = ( 0.625 - ( center * center ) ) / (double) n;
    }
    else
    {
        answer = 3.0 / 16.0;
    }
    return answer;
}
<commit_msg>removed debug message<commit_after>/*
 * LoopSubdivsionivision.cpp
 *
 *  Created on: Sep 3, 2013
 *      Author: schurade
 */

#include "loopsubdivision.h"

#include "../data/mesh/trianglemesh2.h"

#include <QDebug>

LoopSubdivision::~LoopSubdivision()
{
}

LoopSubdivision::LoopSubdivision( TriangleMesh2* mesh ) :
    m_mesh( mesh )
{
    m_mesh = new TriangleMesh2( mesh );

    m_numVerts = m_mesh->numVerts();
    m_numTris = m_mesh->numTris();

    //qDebug() << m_numVerts << m_numTris;

    m_mesh->resize( m_numVerts * 4, m_numTris * 4 );

    QVector<QVector3D> newVertexPositions( m_numVerts );

    for ( int i = 0; i < m_numVerts; ++i )
    {
        newVertexPositions[i] = calcNewPosition( i );
    }

    for ( int i = 0; i < m_numTris; ++i )
    {
        insertCenterTriangle( i );
    }

    for ( int i = 0; i < m_numTris; ++i )
    {
        insertCornerTriangles( i );
    }

    for ( int i = 0; i < m_numVerts; ++i )
    {
        m_mesh->addVertex( i, newVertexPositions[i] );
    }

    m_numVerts = m_mesh->numVerts();
    m_numTris = m_mesh->numTris();

    //qDebug() << m_numVerts << m_numTris;

    m_mesh->finalize();

    newVertexPositions.clear();
    newVertexPositions.squeeze();

}

QVector3D LoopSubdivision::calcNewPosition( int vertNum )
{
    QVector<int> starP = m_mesh->getStar( vertNum );
    int starSize = starP.size();

    QVector3D oldPos = m_mesh->getVertex( vertNum );
    double alpha = getAlpha( starSize );
    oldPos *= ( 1.0 - ( (double) starSize * alpha ) );

    QVector3D newPos;
    int edgeV = 0;
    for ( int i = 0; i < starSize; i++ )
    {
        edgeV = m_mesh->getNextVertex( starP[i], vertNum );
        newPos += m_mesh->getVertex( edgeV );
    }
    newPos *= alpha;

    return oldPos + newPos;
}

void LoopSubdivision::insertCenterTriangle( int triNum )
{

    QVector<int> intP = m_mesh->getTriangle( triNum );
    int edgeVerts[3];

    for ( int i = 0; i < 3; ++i )
    {
        edgeVerts[i] = calcEdgeVert( triNum, intP[i], intP[( i + 1 ) % 3], intP[( i + 2 ) % 3] );
    }
    m_mesh->addTriangle( edgeVerts[0], edgeVerts[1], edgeVerts[2] );
}

void LoopSubdivision::insertCornerTriangles( int triNum )
{

    // comment:     center are twisted from the orignal vertices.
    // original:    0, 1, 2
    // center:      a, b, c
    // reAsgnOrig:  0, a, c
    // addTris:     1, b, a
    // addTris:     2, c, b
    //
    QVector<int> originalTri = m_mesh->getTriangle( triNum );
    QVector<int> centerTri = m_mesh->getTriangle( triNum + m_numTris );

    m_mesh->addTriangle( originalTri[1], centerTri[1], centerTri[0] );
    m_mesh->addTriangle( originalTri[2], centerTri[2], centerTri[1] );
    m_mesh->addTriangle( triNum, originalTri[0], centerTri[0], centerTri[2] );
}

int LoopSubdivision::calcEdgeVert( int triNum, int edgeV1, int edgeV2, int V3 )
{

    int vertNum = -1;

    int neighborVert = -1;
    int neighborFaceNum = -1;
    QVector3D edgeVert;

    neighborFaceNum = m_mesh->getNeighbor( edgeV1, edgeV2, triNum );

    if ( neighborFaceNum == triNum )
    {
        QVector3D edgeVert = ( m_mesh->getVertex( edgeV1 ) + m_mesh->getVertex( edgeV2 ) ) / 2.0;
        vertNum = m_mesh->currentNumVerts();
        m_mesh->addVertex( edgeVert.x(), edgeVert.y(), edgeVert.z() );
    }

    else if ( neighborFaceNum > triNum )
    {
        QVector<int> tri = m_mesh->getTriangle( neighborFaceNum );

        if ( tri[0] == edgeV1 || tri[0] == edgeV2 )
        {
            if ( tri[1] == edgeV1 || tri[1] == edgeV2 )
            {
                neighborVert = tri[2];
            }
            else
            {
                neighborVert = tri[1];
            }
        }
        else
        {
            neighborVert = tri[0];
        }

        QVector3D edgePart = m_mesh->getVertex( edgeV1 ) + m_mesh->getVertex( edgeV2 );
        QVector3D neighborPart = m_mesh->getVertex( neighborVert ) + m_mesh->getVertex( V3 );

        edgeVert = ( ( edgePart * ( 3.0 / 8.0 ) ) + ( neighborPart * ( 1.0 / 8.0 ) ) );
        vertNum = m_mesh->currentNumVerts();
        m_mesh->addVertex( edgeVert.x(), edgeVert.y(), edgeVert.z() );
    }
    else
    {
        QVector<int> neighborCenterP = m_mesh->getTriangle( neighborFaceNum + m_numTris );
        QVector<int> neighborP = m_mesh->getTriangle( neighborFaceNum );

        if ( neighborP[0] == edgeV2 )
        {
            vertNum = neighborCenterP[0];
        }
        else if ( neighborP[1] == edgeV2 )
        {
            vertNum = neighborCenterP[1];
        }
        else
        {
            vertNum = neighborCenterP[2];
        }
    }
    return vertNum;
}

double LoopSubdivision::getAlpha( int n )
{
    double answer;
    if ( n > 3 )
    {
        double center = ( 0.375 + ( 0.25 * cos( ( 2.0 * 3.14159265358979 ) / (double) n ) ) );
        answer = ( 0.625 - ( center * center ) ) / (double) n;
    }
    else
    {
        answer = 3.0 / 16.0;
    }
    return answer;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: cacheaccess.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2004-06-18 15:51:32 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_CACHEACCESS_HXX
#define CONFIGMGR_CACHEACCESS_HXX

#ifndef CONFIGMGR_CACHEDATA_HXX
#include "cachedata.hxx"
#endif
#ifndef CONFIGMGR_TIMESTAMP_HXX
#include "timestamp.hxx"
#endif
#ifndef CONFIGMGR_UTILITY_HXX_
#include "utility.hxx"
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _SALHELPER_SIMPLEREFERENCEOBJECT_HXX_
#include <salhelper/simplereferenceobject.hxx>
#endif
#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

namespace configmgr
{
////////////////////////////////////////////////////////////////////////////////
    using ::rtl::OUString;

    class ConfigChangeBroadcastHelper;
    namespace backend
    {
        class CacheController;
    }
//-----------------------------------------------------------------------------

    class CacheClientAccess : public salhelper::SimpleReferenceObject, Noncopyable
    {
    public:
        typedef CacheData   Data;
        typedef Data::Module       Module;
        typedef Data::ModuleRef    ModuleRef;
        typedef Data::ModuleName   ModuleName;
        typedef Data::Path         Path;
    private:
        osl::Mutex          m_aMutex;
        Data                m_aData;

        ConfigChangeBroadcastHelper* m_pBroadcastHelper;
    public:
        explicit
        CacheClientAccess(memory::HeapManager & _rHeapManager,
                          ConfigChangeBroadcastHelper* _pBroadcastHelper);

        ~CacheClientAccess();

        /// gets a helper to broadcast changes for
        ConfigChangeBroadcastHelper * getBroadcaster() const
        { return m_pBroadcastHelper; }

        /// removes an existing broadcast helper
        ConfigChangeBroadcastHelper * releaseBroadcaster();

        /// gets a data segment reference for the given path - creates if necessary
        memory::Segment * attachDataSegment(const memory::SegmentAddress & _aSegment, const Path& _aLocation);
        /// gets a data segment reference for the given path if exists
        memory::Segment * getDataSegment(const Path& _aLocation);

        /// return TRUE if there is no data (left) in this object's cache data
        bool isEmpty();

        /// check if the given module exists already (and is not empty)
        bool hasModule(const Path& _aLocation);
        /// checks if the given module exists and has defaults available
        bool hasModuleDefaults(memory::Accessor const & _aAccessor, Path const & _aLocation);

        /// retrieve the subtree at _aPath (maybe if it has the requested defaults) and clientAcquire() it
        data::NodeAddress acquireNode(memory::Accessor const& _aAccessToken, Path const& _aPath);

        /** add or merge the given subtree at the given location,
            return <TRUE/> if the tree has defaults then
        */
        bool insertDefaults(memory::UpdateAccessor& _aUpdateToken, backend::NodeInstance const & _aDefaultData ) CFG_UNO_THROW_RTE(  );

        /// clientRelease() the tree at aComponentName, and return the resulting reference count
        CacheLine::RefCount releaseNode( Path const& _aPath );

        /// retrieve the given subtree without changing its ref count
        data::NodeAddress   findInnerNode(memory::Accessor const& _aAccessToken, Path const& _aPath );

        /// merge the given change list into this tree - reflects old data to _aUpdate
        void applyUpdate(memory::UpdateAccessor& _aUpdateToken,  backend::UpdateInstance & _aUpdate) CFG_UNO_THROW_RTE( );
    };

////////////////////////////////////////////////////////////////////////////////

    class CacheLoadingAccess : public salhelper::SimpleReferenceObject, Noncopyable
    {
    public:
        typedef ExtendedCacheData  Data;
        typedef Data::Module       Module;
        typedef Data::ModuleRef    ModuleRef;
        typedef Data::ModuleName   ModuleName;
        typedef Data::Path         Path;

        typedef std::vector< ModuleRef >  DisposeList;
        friend class backend::CacheController;
    private:
        friend class CacheDisposeScheduler;
        typedef std::map< ModuleName, TimeStamp > DeadModuleList;

        osl::Mutex          m_aMutex;
        Data                m_aData;
        DeadModuleList      m_aDeadModules;         /// list of nodes which are registered for throwing away
    public:
        explicit
        CacheLoadingAccess(memory::HeapManager & _rHeapManager);
        ~CacheLoadingAccess();

        /// gets a data segment reference for the given path if exists
        memory::Segment * createNewDataSegment(ModuleName const & _aModule);
        /// gets a data segment reference for the given path - creates if necessary
        memory::Segment * attachDataSegment(const memory::SegmentAddress & _aSegment, ModuleName const & _aModule);
        /// gets a data segment reference for the given path if exists
        memory::Segment * getDataSegment(ModuleName const & _aModule);
        /// gets a data segment address for the given module if it exists
        memory::SegmentAddress getDataSegmentAddress(ModuleName const & _aModule);

        /// return TRUE if there is no data (left) in this object's cache data
        bool isEmpty();

        /// check if the given module exists already (and is not empty)
        bool hasModule(ModuleName const & _aLocation);

        /// retrieve the subtree at aComponentName and clientAcquire() it
        data::TreeAddress acquireModule(ModuleName const & _aModule);

        /// clientRelease() the tree at aComponentName, and return the resulting reference count
        CacheLine::RefCount releaseModule( ModuleName const & _aModule );

        /// retrieve the given subtree without changing its ref count
        data::NodeAddress   findNode(memory::Accessor const& _aAccessToken, Path const& _aPath );

        /// merge the given change list into this tree - reflects old data to _aUpdate
        void applyUpdate(memory::UpdateAccessor& _aUpdateToken,  backend::UpdateInstance & _aUpdate) CFG_UNO_THROW_RTE( );

        /// collect the modules that can be disposed now (i.e. released after _rLimitReleaseTime)
        TimeStamp collectDisposeList(CacheLoadingAccess::DisposeList & _rList,
                                        TimeStamp const & _aLimitTime,
                                        TimeInterval const & _aDelay);

        /// clear the contained tree, return all remaining modules
        void clearData( DisposeList& _rDisposeList) CFG_NOTHROW();

    // stuff that is particular for CacheLoadingAccess
        /** add the given subtree at the given location,
            return the tree that is then pertinent and clientAcquire() it once
        */
        data::TreeAddress addComponentData( memory::UpdateAccessor& _aAccessToken,
                                            backend::ComponentInstance const & _aComponentInstance,
                                            bool _bIncludesDefaults
                                           ) CFG_UNO_THROW_RTE();

        /// merge the given change list into the pending change list of this tree
        void addChangesToPending( backend::ConstUpdateInstance const& _anUpdate ) CFG_UNO_THROW_RTE(  );
        /// retrieve accumulated pending changes
        std::auto_ptr<SubtreeChange> releasePendingChanges(ModuleName const& _aModule);

        /// find the modules having pending changes
        bool findPendingChangedModules( Data::PendingModuleList & _rPendingList );

        /// get a local lock for this cache line
        osl::Mutex & mutex() { return m_aMutex; }
    };

////////////////////////////////////////////////////////////////////////////////

} // namespace configmgr

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.5.74); FILE MERGED 2005/09/05 17:05:11 rt 1.5.74.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cacheaccess.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 04:21:46 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef CONFIGMGR_CACHEACCESS_HXX
#define CONFIGMGR_CACHEACCESS_HXX

#ifndef CONFIGMGR_CACHEDATA_HXX
#include "cachedata.hxx"
#endif
#ifndef CONFIGMGR_TIMESTAMP_HXX
#include "timestamp.hxx"
#endif
#ifndef CONFIGMGR_UTILITY_HXX_
#include "utility.hxx"
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _SALHELPER_SIMPLEREFERENCEOBJECT_HXX_
#include <salhelper/simplereferenceobject.hxx>
#endif
#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif

namespace configmgr
{
////////////////////////////////////////////////////////////////////////////////
    using ::rtl::OUString;

    class ConfigChangeBroadcastHelper;
    namespace backend
    {
        class CacheController;
    }
//-----------------------------------------------------------------------------

    class CacheClientAccess : public salhelper::SimpleReferenceObject, Noncopyable
    {
    public:
        typedef CacheData   Data;
        typedef Data::Module       Module;
        typedef Data::ModuleRef    ModuleRef;
        typedef Data::ModuleName   ModuleName;
        typedef Data::Path         Path;
    private:
        osl::Mutex          m_aMutex;
        Data                m_aData;

        ConfigChangeBroadcastHelper* m_pBroadcastHelper;
    public:
        explicit
        CacheClientAccess(memory::HeapManager & _rHeapManager,
                          ConfigChangeBroadcastHelper* _pBroadcastHelper);

        ~CacheClientAccess();

        /// gets a helper to broadcast changes for
        ConfigChangeBroadcastHelper * getBroadcaster() const
        { return m_pBroadcastHelper; }

        /// removes an existing broadcast helper
        ConfigChangeBroadcastHelper * releaseBroadcaster();

        /// gets a data segment reference for the given path - creates if necessary
        memory::Segment * attachDataSegment(const memory::SegmentAddress & _aSegment, const Path& _aLocation);
        /// gets a data segment reference for the given path if exists
        memory::Segment * getDataSegment(const Path& _aLocation);

        /// return TRUE if there is no data (left) in this object's cache data
        bool isEmpty();

        /// check if the given module exists already (and is not empty)
        bool hasModule(const Path& _aLocation);
        /// checks if the given module exists and has defaults available
        bool hasModuleDefaults(memory::Accessor const & _aAccessor, Path const & _aLocation);

        /// retrieve the subtree at _aPath (maybe if it has the requested defaults) and clientAcquire() it
        data::NodeAddress acquireNode(memory::Accessor const& _aAccessToken, Path const& _aPath);

        /** add or merge the given subtree at the given location,
            return <TRUE/> if the tree has defaults then
        */
        bool insertDefaults(memory::UpdateAccessor& _aUpdateToken, backend::NodeInstance const & _aDefaultData ) CFG_UNO_THROW_RTE(  );

        /// clientRelease() the tree at aComponentName, and return the resulting reference count
        CacheLine::RefCount releaseNode( Path const& _aPath );

        /// retrieve the given subtree without changing its ref count
        data::NodeAddress   findInnerNode(memory::Accessor const& _aAccessToken, Path const& _aPath );

        /// merge the given change list into this tree - reflects old data to _aUpdate
        void applyUpdate(memory::UpdateAccessor& _aUpdateToken,  backend::UpdateInstance & _aUpdate) CFG_UNO_THROW_RTE( );
    };

////////////////////////////////////////////////////////////////////////////////

    class CacheLoadingAccess : public salhelper::SimpleReferenceObject, Noncopyable
    {
    public:
        typedef ExtendedCacheData  Data;
        typedef Data::Module       Module;
        typedef Data::ModuleRef    ModuleRef;
        typedef Data::ModuleName   ModuleName;
        typedef Data::Path         Path;

        typedef std::vector< ModuleRef >  DisposeList;
        friend class backend::CacheController;
    private:
        friend class CacheDisposeScheduler;
        typedef std::map< ModuleName, TimeStamp > DeadModuleList;

        osl::Mutex          m_aMutex;
        Data                m_aData;
        DeadModuleList      m_aDeadModules;         /// list of nodes which are registered for throwing away
    public:
        explicit
        CacheLoadingAccess(memory::HeapManager & _rHeapManager);
        ~CacheLoadingAccess();

        /// gets a data segment reference for the given path if exists
        memory::Segment * createNewDataSegment(ModuleName const & _aModule);
        /// gets a data segment reference for the given path - creates if necessary
        memory::Segment * attachDataSegment(const memory::SegmentAddress & _aSegment, ModuleName const & _aModule);
        /// gets a data segment reference for the given path if exists
        memory::Segment * getDataSegment(ModuleName const & _aModule);
        /// gets a data segment address for the given module if it exists
        memory::SegmentAddress getDataSegmentAddress(ModuleName const & _aModule);

        /// return TRUE if there is no data (left) in this object's cache data
        bool isEmpty();

        /// check if the given module exists already (and is not empty)
        bool hasModule(ModuleName const & _aLocation);

        /// retrieve the subtree at aComponentName and clientAcquire() it
        data::TreeAddress acquireModule(ModuleName const & _aModule);

        /// clientRelease() the tree at aComponentName, and return the resulting reference count
        CacheLine::RefCount releaseModule( ModuleName const & _aModule );

        /// retrieve the given subtree without changing its ref count
        data::NodeAddress   findNode(memory::Accessor const& _aAccessToken, Path const& _aPath );

        /// merge the given change list into this tree - reflects old data to _aUpdate
        void applyUpdate(memory::UpdateAccessor& _aUpdateToken,  backend::UpdateInstance & _aUpdate) CFG_UNO_THROW_RTE( );

        /// collect the modules that can be disposed now (i.e. released after _rLimitReleaseTime)
        TimeStamp collectDisposeList(CacheLoadingAccess::DisposeList & _rList,
                                        TimeStamp const & _aLimitTime,
                                        TimeInterval const & _aDelay);

        /// clear the contained tree, return all remaining modules
        void clearData( DisposeList& _rDisposeList) CFG_NOTHROW();

    // stuff that is particular for CacheLoadingAccess
        /** add the given subtree at the given location,
            return the tree that is then pertinent and clientAcquire() it once
        */
        data::TreeAddress addComponentData( memory::UpdateAccessor& _aAccessToken,
                                            backend::ComponentInstance const & _aComponentInstance,
                                            bool _bIncludesDefaults
                                           ) CFG_UNO_THROW_RTE();

        /// merge the given change list into the pending change list of this tree
        void addChangesToPending( backend::ConstUpdateInstance const& _anUpdate ) CFG_UNO_THROW_RTE(  );
        /// retrieve accumulated pending changes
        std::auto_ptr<SubtreeChange> releasePendingChanges(ModuleName const& _aModule);

        /// find the modules having pending changes
        bool findPendingChangedModules( Data::PendingModuleList & _rPendingList );

        /// get a local lock for this cache line
        osl::Mutex & mutex() { return m_aMutex; }
    };

////////////////////////////////////////////////////////////////////////////////

} // namespace configmgr

#endif

<|endoftext|>


<commit_before>// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
// Copyright 2020 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at:
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
// ----------------------------------------------------------------------------

/**
 * @brief Fuzz target for physical_to_symbolic().
 *
 * This function is the first entrypoint for decompressing a 16 byte block of
 * input ASTC data from disk. The 16 bytes can contain arbitrary data; they
 * are read from an external source, but the block size used must be a valid
 * ASTC block footprint.
 */

#include "astcenc_internal.h"

#include <fuzzer/FuzzedDataProvider.h>
#include <array>
#include <vector>

struct BlockSizes {
	int x;
	int y;
	int z;
};

std::array<BlockSizes, 3> testSz {{
	{ 4,  4, 1}, // Highest bitrate
	{12, 12, 1}, // Largest 2D block
	{6,  6,  6}  // Largest 3D block
}};

std::array<block_size_descriptor, 3> testBSD;

/**
 * @brief Utility function to create all of the block size descriptors needed.
 *
 * This is triggered once via a static initializer.
 *
 * Triggering once is important so that we only create a single BSD per block
 * size we need, rather than one per fuzzer iteration (it's expensive). This
 * improves fuzzer throughput by ~ 1000x!
 *
 * Triggering via a static initializer, rather than a lazy init in the fuzzer
 * function, is important because is means that the BSD is allocated before
 * fuzzing starts. This means that leaksanitizer will ignore the fact that we
 * "leak" the dynamic allocations inside the BSD (we never call term()).
 */
bool bsd_initializer()
{
	for (int i = 0; i < testSz.size(); i++)
	{
		init_block_size_descriptor(
		    testSz[i].x,
		    testSz[i].y,
		    testSz[i].z,
		    &(testBSD[i]));
	}

	return true;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
	// Preinitialize the block size descriptors we need
	static bool init = bsd_initializer();

	// Must have 4 (select block size) and 16 (payload) bytes
	if (size < 4 + 16)
	{
		return 0;
	}

	FuzzedDataProvider stream(data, size);

	// Select a block size to test
	int i = stream.ConsumeIntegralInRange<int>(0, testSz.size() - 1);
	block_size_descriptor* bsd = &(testBSD[i]);

	// Populate the physical block
	physical_compressed_block pcb;
	std::vector<uint8_t> buffer = stream.ConsumeBytes<uint8_t>(16);
	std::memcpy(&pcb, buffer.data(), 16);

	// Call the function under test
	symbolic_compressed_block scb;
	physical_to_symbolic(bsd, pcb, &scb);

	return 0;
}
<commit_msg>Update fuzz test to new API<commit_after>// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
// Copyright 2020 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at:
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
// ----------------------------------------------------------------------------

/**
 * @brief Fuzz target for physical_to_symbolic().
 *
 * This function is the first entrypoint for decompressing a 16 byte block of
 * input ASTC data from disk. The 16 bytes can contain arbitrary data; they
 * are read from an external source, but the block size used must be a valid
 * ASTC block footprint.
 */

#include "astcenc_internal.h"

#include <fuzzer/FuzzedDataProvider.h>
#include <array>
#include <vector>

struct BlockSizes {
	int x;
	int y;
	int z;
};

std::array<BlockSizes, 3> testSz {{
	{ 4,  4, 1}, // Highest bitrate
	{12, 12, 1}, // Largest 2D block
	{6,  6,  6}  // Largest 3D block
}};

std::array<block_size_descriptor, 3> testBSD;

/**
 * @brief Utility function to create all of the block size descriptors needed.
 *
 * This is triggered once via a static initializer.
 *
 * Triggering once is important so that we only create a single BSD per block
 * size we need, rather than one per fuzzer iteration (it's expensive). This
 * improves fuzzer throughput by ~ 1000x!
 *
 * Triggering via a static initializer, rather than a lazy init in the fuzzer
 * function, is important because is means that the BSD is allocated before
 * fuzzing starts. This means that leaksanitizer will ignore the fact that we
 * "leak" the dynamic allocations inside the BSD (we never call term()).
 */
bool bsd_initializer()
{
	for (int i = 0; i < testSz.size(); i++)
	{
		init_block_size_descriptor(
		    testSz[i].x,
		    testSz[i].y,
		    testSz[i].z,
		    &(testBSD[i]));
	}

	return true;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
	// Preinitialize the block size descriptors we need
	static bool init = bsd_initializer();

	// Must have 4 (select block size) and 16 (payload) bytes
	if (size < 4 + 16)
	{
		return 0;
	}

	FuzzedDataProvider stream(data, size);

	// Select a block size to test
	int i = stream.ConsumeIntegralInRange<int>(0, testSz.size() - 1);

	// Populate the physical block
	physical_compressed_block pcb;
	std::vector<uint8_t> buffer = stream.ConsumeBytes<uint8_t>(16);
	std::memcpy(&pcb, buffer.data(), 16);

	// Call the function under test
	symbolic_compressed_block scb;
	physical_to_symbolic(testBSD[i], pcb, scb);

	return 0;
}
<|endoftext|>