<commit_before>/*************************************************************************
 *
 * Copyright 2016 Realm Inc.
 *
 * 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.
 *
 **************************************************************************/

#ifndef REALM_UTIL_INTERPROCESS_MUTEX
#define REALM_UTIL_INTERPROCESS_MUTEX

#include <realm/util/features.h>
#include <realm/util/thread.hpp>
#include <realm/util/file.hpp>
#include <realm/utilities.hpp>
#include <mutex>
#include <map>

// Enable this only on platforms where it might be needed
#if REALM_PLATFORM_APPLE || REALM_ANDROID
#define REALM_ROBUST_MUTEX_EMULATION
#endif

namespace realm {
namespace util {

// fwd decl to support friend decl below
class InterprocessCondVar;

/// Emulation of a Robust Mutex.
/// A Robust Mutex is an interprocess mutex which will automatically
/// release any locks held by a process when it crashes. Contrary to
/// Posix robust mutexes, this robust mutex is not capable of informing
/// participants that they have been granted a lock after a crash of
/// the process holding it (though it could be added if needed).

class InterprocessMutex {
public:
    InterprocessMutex();
    ~InterprocessMutex() noexcept;

    // Disable copying. Copying a locked Mutex will create a scenario
    // where the same file descriptor will be locked once but unlocked twice.
    InterprocessMutex(const InterprocessMutex&) = delete;
    InterprocessMutex& operator=(const InterprocessMutex&) = delete;

#ifdef REALM_ROBUST_MUTEX_EMULATION
    struct SharedPart {
    };
#else
    using SharedPart = RobustMutex;
#endif

    /// You need to bind the emulation to a SharedPart in shared/mmapped memory.
    /// The SharedPart is assumed to have been initialized (possibly by another process)
    /// elsewhere.
    void set_shared_part(SharedPart& shared_part, const std::string& path, const std::string& mutex_name);
    void set_shared_part(SharedPart& shared_part, File&& lock_file);

    /// Destroy shared object. Potentially release system resources. Caller must
    /// ensure that the shared_part is not in use at the point of call.
    void release_shared_part();

    /// Lock the mutex. If the mutex is already locked, wait for it to be unlocked.
    void lock();

    /// Unlock the mutex
    void unlock();

    /// Attempt to check if the mutex is valid (only relevant if not emulating)
    bool is_valid() noexcept;

    static bool is_robust_on_this_platform()
    {
#ifdef REALM_ROBUST_MUTEX_EMULATION
        return true; // we're faking it!
#else
        return RobustMutex::is_robust_on_this_platform();
#endif
    }

private:
#ifdef REALM_ROBUST_MUTEX_EMULATION
    struct LockInfo {
        File m_file;
        Mutex m_local_mutex;
        LockInfo() {}
        ~LockInfo() noexcept;
        // Disable copying.
        LockInfo(const LockInfo&) = delete;
        LockInfo& operator=(const LockInfo&) = delete;
    };
    /// InterprocessMutex created on the same file (same inode on POSIX) share the same LockInfo.
    /// LockInfo will be saved in a static map as a weak ptr and use the UniqueID as the key.
    /// Operations on the map need to be protected by s_mutex
    static std::map<File::UniqueID, std::weak_ptr<LockInfo>>* s_info_map;
    static Mutex* s_mutex;
    /// We manually initialize these static variables when first needed,
    /// creating them on the heap so that they last for the entire lifetime
    /// of the process. The destructor of these is never called; the
    /// process will clean up their memory when exiting. It is not enough
    /// to count instances of InterprocessMutex and clean up these statics when
    /// the count reaches zero because the program can create more
    /// InterprocessMutex instances before the process ends, so we really need
    /// these variables for the entire lifetime of the process.
    static std::once_flag s_init_flag;
    static void initialize_statics();

    /// Only used for release_shared_part
    std::string m_filename;
    File::UniqueID m_fileuid;
    std::shared_ptr<LockInfo> m_lock_info;

    /// Free the lock info hold by this instance.
    /// If it is the last reference, underly resources will be freed as well.
    void free_lock_info();
#else
    SharedPart* m_shared_part = nullptr;
#endif
    friend class InterprocessCondVar;
};

inline InterprocessMutex::InterprocessMutex()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    std::call_once(s_init_flag, initialize_statics);
#endif
}

inline InterprocessMutex::~InterprocessMutex() noexcept
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    free_lock_info();
#endif
}

#ifdef REALM_ROBUST_MUTEX_EMULATION
inline InterprocessMutex::LockInfo::~LockInfo() noexcept
{
    if (m_file.is_attached()) {
        m_file.close();
    }
}

inline void InterprocessMutex::free_lock_info()
{
    // It has not been initiated yet.
    if (!m_lock_info)
        return;

    std::lock_guard<Mutex> guard(*s_mutex);

    m_lock_info.reset();
    if ((*s_info_map)[m_fileuid].expired()) {
        s_info_map->erase(m_fileuid);
    }
    m_filename.clear();
}

inline void InterprocessMutex::initialize_statics()
{
    s_mutex = new Mutex();
    s_info_map = new std::map<File::UniqueID, std::weak_ptr<LockInfo>>();
}
#endif

inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, const std::string& path,
                                               const std::string& mutex_name)
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    static_cast<void>(shared_part);

    free_lock_info();

    m_filename = path + "." + mutex_name + ".mx";

    std::lock_guard<Mutex> guard(*s_mutex);

    // Try to get the file uid if the file exists
    if (File::get_unique_id(m_filename, m_fileuid)) {
        auto result = s_info_map->find(m_fileuid);
        if (result != s_info_map->end()) {
            // File exists and the lock info has been created in the map.
            m_lock_info = result->second.lock();
            return;
        }
    }

    // LockInfo has not been created yet.
    m_lock_info = std::make_shared<LockInfo>();
    // Always use mod_Write to open file and retreive the uid in case other process
    // deletes the file.
    m_lock_info->m_file.open(m_filename, File::mode_Write);
    m_fileuid = m_lock_info->m_file.get_unique_id();

    (*s_info_map)[m_fileuid] = m_lock_info;
#else
    m_shared_part = &shared_part;
    static_cast<void>(path);
    static_cast<void>(mutex_name);
#endif
}

inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, File&& lock_file)
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    static_cast<void>(shared_part);

    free_lock_info();

    std::lock_guard<Mutex> guard(*s_mutex);

    m_fileuid = lock_file.get_unique_id();
    auto result = s_info_map->find(m_fileuid);
    if (result == s_info_map->end()) {
        m_lock_info = std::make_shared<LockInfo>();
        m_lock_info->m_file = std::move(lock_file);
        (*s_info_map)[m_fileuid] = m_lock_info;
    }
    else {
        // File exists and the lock info has been created in the map.
        m_lock_info = result->second.lock();
        lock_file.close();
    }
#else
    m_shared_part = &shared_part;
    static_cast<void>(lock_file);
#endif
}

inline void InterprocessMutex::release_shared_part()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    if (!m_filename.empty())
        File::try_remove(m_filename);

    free_lock_info();
#else
    m_shared_part = nullptr;
#endif
}

inline void InterprocessMutex::lock()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    std::unique_lock<Mutex> mutex_lock(m_lock_info->m_local_mutex);
    m_lock_info->m_file.lock_exclusive();
    mutex_lock.release();
#else
    REALM_ASSERT(m_shared_part);
    m_shared_part->lock([]() {});
#endif
}

inline void InterprocessMutex::unlock()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    m_lock_info->m_file.unlock();
    m_lock_info->m_local_mutex.unlock();
#else
    REALM_ASSERT(m_shared_part);
    m_shared_part->unlock();
#endif
}

inline bool InterprocessMutex::is_valid() noexcept
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    return true;
#else
    REALM_ASSERT(m_shared_part);
    return m_shared_part->is_valid();
#endif
}

} // namespace util
} // namespace realm

#endif // #ifndef REALM_UTIL_INTERPROCESS_MUTEX
<commit_msg>Spelling error in comment.<commit_after>/*************************************************************************
 *
 * Copyright 2016 Realm Inc.
 *
 * 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.
 *
 **************************************************************************/

#ifndef REALM_UTIL_INTERPROCESS_MUTEX
#define REALM_UTIL_INTERPROCESS_MUTEX

#include <realm/util/features.h>
#include <realm/util/thread.hpp>
#include <realm/util/file.hpp>
#include <realm/utilities.hpp>
#include <mutex>
#include <map>

// Enable this only on platforms where it might be needed
#if REALM_PLATFORM_APPLE || REALM_ANDROID
#define REALM_ROBUST_MUTEX_EMULATION
#endif

namespace realm {
namespace util {

// fwd decl to support friend decl below
class InterprocessCondVar;

/// Emulation of a Robust Mutex.
/// A Robust Mutex is an interprocess mutex which will automatically
/// release any locks held by a process when it crashes. Contrary to
/// Posix robust mutexes, this robust mutex is not capable of informing
/// participants that they have been granted a lock after a crash of
/// the process holding it (though it could be added if needed).

class InterprocessMutex {
public:
    InterprocessMutex();
    ~InterprocessMutex() noexcept;

    // Disable copying. Copying a locked Mutex will create a scenario
    // where the same file descriptor will be locked once but unlocked twice.
    InterprocessMutex(const InterprocessMutex&) = delete;
    InterprocessMutex& operator=(const InterprocessMutex&) = delete;

#ifdef REALM_ROBUST_MUTEX_EMULATION
    struct SharedPart {
    };
#else
    using SharedPart = RobustMutex;
#endif

    /// You need to bind the emulation to a SharedPart in shared/mmapped memory.
    /// The SharedPart is assumed to have been initialized (possibly by another process)
    /// elsewhere.
    void set_shared_part(SharedPart& shared_part, const std::string& path, const std::string& mutex_name);
    void set_shared_part(SharedPart& shared_part, File&& lock_file);

    /// Destroy shared object. Potentially release system resources. Caller must
    /// ensure that the shared_part is not in use at the point of call.
    void release_shared_part();

    /// Lock the mutex. If the mutex is already locked, wait for it to be unlocked.
    void lock();

    /// Unlock the mutex
    void unlock();

    /// Attempt to check if the mutex is valid (only relevant if not emulating)
    bool is_valid() noexcept;

    static bool is_robust_on_this_platform()
    {
#ifdef REALM_ROBUST_MUTEX_EMULATION
        return true; // we're faking it!
#else
        return RobustMutex::is_robust_on_this_platform();
#endif
    }

private:
#ifdef REALM_ROBUST_MUTEX_EMULATION
    struct LockInfo {
        File m_file;
        Mutex m_local_mutex;
        LockInfo() {}
        ~LockInfo() noexcept;
        // Disable copying.
        LockInfo(const LockInfo&) = delete;
        LockInfo& operator=(const LockInfo&) = delete;
    };
    /// InterprocessMutex created on the same file (same inode on POSIX) share the same LockInfo.
    /// LockInfo will be saved in a static map as a weak ptr and use the UniqueID as the key.
    /// Operations on the map need to be protected by s_mutex
    static std::map<File::UniqueID, std::weak_ptr<LockInfo>>* s_info_map;
    static Mutex* s_mutex;
    /// We manually initialize these static variables when first needed,
    /// creating them on the heap so that they last for the entire lifetime
    /// of the process. The destructor of these is never called; the
    /// process will clean up their memory when exiting. It is not enough
    /// to count instances of InterprocessMutex and clean up these statics when
    /// the count reaches zero because the program can create more
    /// InterprocessMutex instances before the process ends, so we really need
    /// these variables for the entire lifetime of the process.
    static std::once_flag s_init_flag;
    static void initialize_statics();

    /// Only used for release_shared_part
    std::string m_filename;
    File::UniqueID m_fileuid;
    std::shared_ptr<LockInfo> m_lock_info;

    /// Free the lock info hold by this instance.
    /// If it is the last reference, underly resources will be freed as well.
    void free_lock_info();
#else
    SharedPart* m_shared_part = nullptr;
#endif
    friend class InterprocessCondVar;
};

inline InterprocessMutex::InterprocessMutex()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    std::call_once(s_init_flag, initialize_statics);
#endif
}

inline InterprocessMutex::~InterprocessMutex() noexcept
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    free_lock_info();
#endif
}

#ifdef REALM_ROBUST_MUTEX_EMULATION
inline InterprocessMutex::LockInfo::~LockInfo() noexcept
{
    if (m_file.is_attached()) {
        m_file.close();
    }
}

inline void InterprocessMutex::free_lock_info()
{
    // It has not been initialized yet.
    if (!m_lock_info)
        return;

    std::lock_guard<Mutex> guard(*s_mutex);

    m_lock_info.reset();
    if ((*s_info_map)[m_fileuid].expired()) {
        s_info_map->erase(m_fileuid);
    }
    m_filename.clear();
}

inline void InterprocessMutex::initialize_statics()
{
    s_mutex = new Mutex();
    s_info_map = new std::map<File::UniqueID, std::weak_ptr<LockInfo>>();
}
#endif

inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, const std::string& path,
                                               const std::string& mutex_name)
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    static_cast<void>(shared_part);

    free_lock_info();

    m_filename = path + "." + mutex_name + ".mx";

    std::lock_guard<Mutex> guard(*s_mutex);

    // Try to get the file uid if the file exists
    if (File::get_unique_id(m_filename, m_fileuid)) {
        auto result = s_info_map->find(m_fileuid);
        if (result != s_info_map->end()) {
            // File exists and the lock info has been created in the map.
            m_lock_info = result->second.lock();
            return;
        }
    }

    // LockInfo has not been created yet.
    m_lock_info = std::make_shared<LockInfo>();
    // Always use mod_Write to open file and retreive the uid in case other process
    // deletes the file.
    m_lock_info->m_file.open(m_filename, File::mode_Write);
    m_fileuid = m_lock_info->m_file.get_unique_id();

    (*s_info_map)[m_fileuid] = m_lock_info;
#else
    m_shared_part = &shared_part;
    static_cast<void>(path);
    static_cast<void>(mutex_name);
#endif
}

inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, File&& lock_file)
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    static_cast<void>(shared_part);

    free_lock_info();

    std::lock_guard<Mutex> guard(*s_mutex);

    m_fileuid = lock_file.get_unique_id();
    auto result = s_info_map->find(m_fileuid);
    if (result == s_info_map->end()) {
        m_lock_info = std::make_shared<LockInfo>();
        m_lock_info->m_file = std::move(lock_file);
        (*s_info_map)[m_fileuid] = m_lock_info;
    }
    else {
        // File exists and the lock info has been created in the map.
        m_lock_info = result->second.lock();
        lock_file.close();
    }
#else
    m_shared_part = &shared_part;
    static_cast<void>(lock_file);
#endif
}

inline void InterprocessMutex::release_shared_part()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    if (!m_filename.empty())
        File::try_remove(m_filename);

    free_lock_info();
#else
    m_shared_part = nullptr;
#endif
}

inline void InterprocessMutex::lock()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    std::unique_lock<Mutex> mutex_lock(m_lock_info->m_local_mutex);
    m_lock_info->m_file.lock_exclusive();
    mutex_lock.release();
#else
    REALM_ASSERT(m_shared_part);
    m_shared_part->lock([]() {});
#endif
}

inline void InterprocessMutex::unlock()
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    m_lock_info->m_file.unlock();
    m_lock_info->m_local_mutex.unlock();
#else
    REALM_ASSERT(m_shared_part);
    m_shared_part->unlock();
#endif
}

inline bool InterprocessMutex::is_valid() noexcept
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    return true;
#else
    REALM_ASSERT(m_shared_part);
    return m_shared_part->is_valid();
#endif
}

} // namespace util
} // namespace realm

#endif // #ifndef REALM_UTIL_INTERPROCESS_MUTEX
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include "utList.h"

int main( int argc , char **argv )
{
    testing :: InitGoogleTest( &argc , argv ) ;
    return RUN_ALL_TESTS( ) ;
}
<commit_msg>Delete mainStructure.cpp<commit_after><|endoftext|>


<commit_before>/** Copyright (C) 2017 Ultimaker - Released under terms of the AGPLv3 License */

#include <iterator>
#include <algorithm>
#include <math.h>
#include "AdaptiveLayerHeights.h"

namespace cura
{

AdaptiveLayer::AdaptiveLayer(int layer_height)
{
    this->layer_height = layer_height;
}

AdaptiveLayerHeights::AdaptiveLayerHeights(Mesh* mesh, int layer_thickness, int initial_layer_thickness, coord_t variation, coord_t step_size, double threshold)
{
    // store the required parameters
    this->mesh = mesh;
    this->layer_height = layer_thickness;
    this->initial_layer_height = initial_layer_thickness;
    this->max_variation = static_cast<int>(variation);
    this->step_size = static_cast<int>(step_size);
    this->threshold = threshold;

    // calculate the allowed layer heights from variation and step size
    // note: the order is from thickest to thinnest height!
    for (int allowed_layer_height = this->layer_height + this->max_variation; allowed_layer_height >= this->layer_height - this->max_variation; allowed_layer_height -= this->step_size)
    {
        this->allowed_layer_heights.push_back(allowed_layer_height);
    }

    this->calculateMeshTriangleSlopes();
    this->calculateLayers();
}

int AdaptiveLayerHeights::getLayerCount()
{
    return this->layers.size();
}

std::vector<AdaptiveLayer>* AdaptiveLayerHeights::getLayers()
{
    return &this->layers;
}

void AdaptiveLayerHeights::calculateLayers()
{
    const int minimum_layer_height = *std::min_element(this->allowed_layer_heights.begin(), this->allowed_layer_heights.end());
    SlicingTolerance slicing_tolerance = this->mesh->getSettingAsSlicingTolerance("slicing_tolerance");
    std::vector<int> triangles_of_interest;
    int z_level = 0;
    int previous_layer_height = 0;

    // the first layer has it's own independent height set, so we always add that
    z_level += this->initial_layer_height;

    // compensate first layer thickness depending on slicing mode
    if (slicing_tolerance == SlicingTolerance::MIDDLE)
    {
        z_level += this->initial_layer_height / 2;
        this->initial_layer_height += this->initial_layer_height / 2;
    }

    auto * adaptive_layer = new AdaptiveLayer(this->initial_layer_height);
    adaptive_layer->z_position = z_level;
    previous_layer_height = adaptive_layer->layer_height;
    this->layers.push_back(*adaptive_layer);

    // loop while triangles are found
    while (!triangles_of_interest.empty() || this->layers.size() < 2)
    {
        // loop over all allowed layer heights starting with the largest
        for (auto & layer_height : this->allowed_layer_heights)
        {
            int lower_bound = z_level;
            int upper_bound = z_level + layer_height;

            std::vector<int> min_bounds;
            std::vector<int> max_bounds;

            // calculate all intersecting lower bounds
            for (auto it_lower = this->face_min_z_values.begin(); it_lower != this->face_min_z_values.end(); ++it_lower)
            {
                if (*it_lower <= upper_bound)
                {
                    min_bounds.emplace_back(std::distance(this->face_min_z_values.begin(), it_lower));
                }
            }

            // calculate all intersecting upper bounds
            for (auto it_upper = this->face_max_z_values.begin(); it_upper != this->face_max_z_values.end(); ++it_upper)
            {
                if (*it_upper >= lower_bound)
                {
                    max_bounds.emplace_back(std::distance(this->face_max_z_values.begin(), it_upper));
                }
            }

            // use lower and upper bounds to filter on triangles that are interesting for this potential layer
            triangles_of_interest.clear();
            std::set_intersection(min_bounds.begin(), min_bounds.end(), max_bounds.begin(), max_bounds.end(), std::back_inserter(triangles_of_interest));

            // when there not interesting triangles in this potential layer go to the next one
            if (triangles_of_interest.empty())
            {
                break;
            }

            std::vector<double> slopes;

            // find all slopes for interesting triangles
            for (auto & triangle_index : triangles_of_interest)
            {
                double slope = this->face_slopes.at(triangle_index);
                slopes.push_back(slope);
            }

            double minimum_slope = *std::min_element(slopes.begin(), slopes.end());
            double minimum_slope_tan = std::tan(minimum_slope);

            // check if the maximum step size has been exceeded depending on layer height direction
            bool has_exceeded_step_size = false;
            if (previous_layer_height > layer_height && previous_layer_height - layer_height > this->step_size)
            {
                has_exceeded_step_size = true;
            }
            else if (layer_height - previous_layer_height > this->step_size && layer_height > minimum_layer_height)
            {
                continue;
            }

            // we add the layer in the following cases:
            // 1) the layer angle is below the threshold and the layer height difference with the previous layer is the maximum allowed step size
            // 2) the layer height is the smallest it is allowed
            // 3) the layer is a flat surface (we can't divide by 0)
            if (minimum_slope_tan == 0.0
                || (layer_height / minimum_slope_tan) <= this->threshold
                || layer_height == minimum_layer_height
                || has_exceeded_step_size)
            {
                z_level += layer_height;
                auto * adaptive_layer = new AdaptiveLayer(layer_height);
                adaptive_layer->z_position = z_level;
                previous_layer_height = adaptive_layer->layer_height;
                this->layers.push_back(*adaptive_layer);
                break;
            }
        }

        // stop calculating when we're out of triangles (e.g. above the mesh)
        if (triangles_of_interest.empty())
        {
            break;
        }
    }
}

void AdaptiveLayerHeights::calculateMeshTriangleSlopes()
{
    // loop over all mesh faces (triangles) and find their slopes
    for (const auto &face : this->mesh->faces)
    {
        const MeshVertex& v0 = this->mesh->vertices[face.vertex_index[0]];
        const MeshVertex& v1 = this->mesh->vertices[face.vertex_index[1]];
        const MeshVertex& v2 = this->mesh->vertices[face.vertex_index[2]];

        FPoint3 p0 = v0.p;
        FPoint3 p1 = v1.p;
        FPoint3 p2 = v2.p;

        float minZ = p0.z;
        float maxZ = p0.z;

        if (p1.z < minZ) minZ = p1.z;
        if (p2.z < minZ) minZ = p2.z;
        if (p1.z > maxZ) maxZ = p1.z;
        if (p2.z > maxZ) maxZ = p2.z;

        // calculate the angle of this triangle in the z direction
        FPoint3 n = FPoint3(p1 - p0).cross(p2 - p0);
        FPoint3 normal = n.normalized();
        double z_angle = std::acos(std::abs(normal.z));

        // prevent flat surfaces from influencing the algorithm
        if (z_angle == 0)
        {
            z_angle = M_PI;
        }

        this->face_min_z_values.push_back(minZ * 1000);
        this->face_max_z_values.push_back(maxZ * 1000);
        this->face_slopes.push_back(z_angle);
    }
}

}<commit_msg>Make search for interesting triangles more efficient.<commit_after>/** Copyright (C) 2017 Ultimaker - Released under terms of the AGPLv3 License */

#include <iterator>
#include <algorithm>
#include <math.h>
#include "AdaptiveLayerHeights.h"

namespace cura
{

AdaptiveLayer::AdaptiveLayer(int layer_height)
{
    this->layer_height = layer_height;
}

AdaptiveLayerHeights::AdaptiveLayerHeights(Mesh* mesh, int layer_thickness, int initial_layer_thickness, coord_t variation, coord_t step_size, double threshold)
{
    // store the required parameters
    this->mesh = mesh;
    this->layer_height = layer_thickness;
    this->initial_layer_height = initial_layer_thickness;
    this->max_variation = static_cast<int>(variation);
    this->step_size = static_cast<int>(step_size);
    this->threshold = threshold;

    // calculate the allowed layer heights from variation and step size
    // note: the order is from thickest to thinnest height!
    for (int allowed_layer_height = this->layer_height + this->max_variation; allowed_layer_height >= this->layer_height - this->max_variation; allowed_layer_height -= this->step_size)
    {
        this->allowed_layer_heights.push_back(allowed_layer_height);
    }

    this->calculateMeshTriangleSlopes();
    this->calculateLayers();
}

int AdaptiveLayerHeights::getLayerCount()
{
    return this->layers.size();
}

std::vector<AdaptiveLayer>* AdaptiveLayerHeights::getLayers()
{
    return &this->layers;
}

void AdaptiveLayerHeights::calculateLayers()
{
    const int minimum_layer_height = *std::min_element(this->allowed_layer_heights.begin(), this->allowed_layer_heights.end());
    SlicingTolerance slicing_tolerance = this->mesh->getSettingAsSlicingTolerance("slicing_tolerance");
    std::vector<int> triangles_of_interest;
    int z_level = 0;
    int previous_layer_height = 0;

    // the first layer has it's own independent height set, so we always add that
    z_level += this->initial_layer_height;

    // compensate first layer thickness depending on slicing mode
    if (slicing_tolerance == SlicingTolerance::MIDDLE)
    {
        z_level += this->initial_layer_height / 2;
        this->initial_layer_height += this->initial_layer_height / 2;
    }

    auto * adaptive_layer = new AdaptiveLayer(this->initial_layer_height);
    adaptive_layer->z_position = z_level;
    previous_layer_height = adaptive_layer->layer_height;
    this->layers.push_back(*adaptive_layer);

    // loop while triangles are found
    while (!triangles_of_interest.empty() || this->layers.size() < 2)
    {
        // loop over all allowed layer heights starting with the largest
        for (auto & layer_height : this->allowed_layer_heights)
        {
            // use lower and upper bounds to filter on triangles that are interesting for this potential layer
            const int lower_bound = z_level;
            const int upper_bound = z_level + layer_height;

            triangles_of_interest.clear();

            for (unsigned int i = 0; i < this->face_min_z_values.size(); ++i)
            {
                if (this->face_min_z_values[i] <= upper_bound && this->face_max_z_values[i] >= lower_bound)
                {
                    triangles_of_interest.push_back(i);
                }
            }

            // when there not interesting triangles in this potential layer go to the next one
            if (triangles_of_interest.empty())
            {
                break;
            }

            std::vector<double> slopes;

            // find all slopes for interesting triangles
            for (auto & triangle_index : triangles_of_interest)
            {
                double slope = this->face_slopes.at(triangle_index);
                slopes.push_back(slope);
            }

            double minimum_slope = *std::min_element(slopes.begin(), slopes.end());
            double minimum_slope_tan = std::tan(minimum_slope);

            // check if the maximum step size has been exceeded depending on layer height direction
            bool has_exceeded_step_size = false;
            if (previous_layer_height > layer_height && previous_layer_height - layer_height > this->step_size)
            {
                has_exceeded_step_size = true;
            }
            else if (layer_height - previous_layer_height > this->step_size && layer_height > minimum_layer_height)
            {
                continue;
            }

            // we add the layer in the following cases:
            // 1) the layer angle is below the threshold and the layer height difference with the previous layer is the maximum allowed step size
            // 2) the layer height is the smallest it is allowed
            // 3) the layer is a flat surface (we can't divide by 0)
            if (minimum_slope_tan == 0.0
                || (layer_height / minimum_slope_tan) <= this->threshold
                || layer_height == minimum_layer_height
                || has_exceeded_step_size)
            {
                z_level += layer_height;
                auto * adaptive_layer = new AdaptiveLayer(layer_height);
                adaptive_layer->z_position = z_level;
                previous_layer_height = adaptive_layer->layer_height;
                this->layers.push_back(*adaptive_layer);
                break;
            }
        }

        // stop calculating when we're out of triangles (e.g. above the mesh)
        if (triangles_of_interest.empty())
        {
            break;
        }
    }
}

void AdaptiveLayerHeights::calculateMeshTriangleSlopes()
{
    // loop over all mesh faces (triangles) and find their slopes
    for (const auto &face : this->mesh->faces)
    {
        const MeshVertex& v0 = this->mesh->vertices[face.vertex_index[0]];
        const MeshVertex& v1 = this->mesh->vertices[face.vertex_index[1]];
        const MeshVertex& v2 = this->mesh->vertices[face.vertex_index[2]];

        FPoint3 p0 = v0.p;
        FPoint3 p1 = v1.p;
        FPoint3 p2 = v2.p;

        float minZ = p0.z;
        float maxZ = p0.z;

        if (p1.z < minZ) minZ = p1.z;
        if (p2.z < minZ) minZ = p2.z;
        if (p1.z > maxZ) maxZ = p1.z;
        if (p2.z > maxZ) maxZ = p2.z;

        // calculate the angle of this triangle in the z direction
        FPoint3 n = FPoint3(p1 - p0).cross(p2 - p0);
        FPoint3 normal = n.normalized();
        double z_angle = std::acos(std::abs(normal.z));

        // prevent flat surfaces from influencing the algorithm
        if (z_angle == 0)
        {
            z_angle = M_PI;
        }

        this->face_min_z_values.push_back(minZ * 1000);
        this->face_max_z_values.push_back(maxZ * 1000);
        this->face_slopes.push_back(z_angle);
    }
}

}<|endoftext|>


<commit_before>#include <systems/OpenGLTextureRenderer.h>

OpenGLTextureRenderer::OpenGLTextureRenderer() : Base(anax::ComponentFilter().requires<Texcoords, PhysicsComponent>()) {

}

OpenGLTextureRenderer::~OpenGLTextureRenderer() {
}

void OpenGLTextureRenderer::render() {
	auto entities = getEntities();
	const float M2P = 30;
	int s = entities.size();
	for (auto entity : entities) {
		auto& texCoordsComp = entity.getComponent<Texcoords>();
		auto& physicsComp = entity.getComponent<PhysicsComponent>();
		auto& image = texCoordsComp.image;

		auto& texCoordsVec = texCoordsComp.textCoords;
		b2Body* body = physicsComp.physicsBody;

		GLuint texture = 0;
		{
//			if (!image.loadFromFile("1.png"))
//				return;
//			image.flipVertically();
			glGenTextures(1, &texture);
			glBindTexture(GL_TEXTURE_2D, texture);
			gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.getSize().x,
					image.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE,
					image.getPixelsPtr());
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
					GL_LINEAR_MIPMAP_LINEAR);
		}

		glBindTexture(GL_TEXTURE_2D, texture);
		glDisableClientState(GL_NORMAL_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);

		b2PolygonShape* shape =
				((b2PolygonShape*) body->GetFixtureList()->GetShape());
		std::vector<b2Vec2> points(shape->GetVertexCount());
		for (int i = 0; i < shape->GetVertexCount(); i++) {
			points[i] = (shape)->GetVertex(i);
		}

		glPushMatrix();
		b2Vec2 center = physicsComp.smoothedPosition;
		float angle = body->GetAngle();
		glTranslatef(static_cast<float>(floor(center.x * M2P)), static_cast<float>(floor(center.y * M2P)), 0.0f);
		glRotatef(angle * 180.0 / M_PI, 0, 0, 1);

		glBegin(GL_POLYGON); //begin drawing of polygon
		for (int i = 0; i < shape->GetVertexCount(); i++) {
				glTexCoord2d(texCoordsVec[i].x, texCoordsVec[i].y);
			glVertex2f(floor(points[i].x * M2P), floor(points[i].y * M2P));
		}
		glEnd(); //end drawing of polygon
		glPopMatrix();
	}

}
<commit_msg>Updated code to use simple opengl calls for textures<commit_after>#include <systems/OpenGLTextureRenderer.h>

OpenGLTextureRenderer::OpenGLTextureRenderer() : Base(anax::ComponentFilter().requires<Texcoords, PhysicsComponent>()) {

}

OpenGLTextureRenderer::~OpenGLTextureRenderer() {
}

void OpenGLTextureRenderer::render() {
	auto entities = getEntities();
	const float M2P = 30.0f;
	for (auto entity : entities) {
		auto& texCoordsComp = entity.getComponent<Texcoords>();
		auto& physicsComp = entity.getComponent<PhysicsComponent>();
		auto& image = texCoordsComp.image;

		auto& texCoordsVec = texCoordsComp.textCoords;
		b2Body* body = physicsComp.physicsBody;

		GLuint texture = 0;
		{
//			if (!image.loadFromFile("1.png"))
//				return;
//			image.flipVertically();
			glGenTextures(1, &texture);
			glBindTexture(GL_TEXTURE_2D, texture);
			gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.getSize().x,
					image.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE,
					image.getPixelsPtr());
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
					GL_LINEAR_MIPMAP_LINEAR);
		}

		glBindTexture(GL_TEXTURE_2D, texture);
		glDisableClientState(GL_NORMAL_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);

		b2PolygonShape* shape =
				((b2PolygonShape*) body->GetFixtureList()->GetShape());
		std::vector<b2Vec2> points(shape->GetVertexCount());
		for (int i = 0; i < shape->GetVertexCount(); i++) {
			points[i] = (shape)->GetVertex(i);
		}

		glPushMatrix();
//		b2Vec2 center = physicsComp.smoothedPosition;
		b2Vec2 center = physicsComp.physicsBody->GetPosition();

		float angle = body->GetAngle();
		glTranslatef(static_cast<float>(floor(center.x * M2P)), static_cast<float>(floor(center.y * M2P)), 0.0f);
		glRotatef(angle * 180.0 / M_PI, 0, 0, 1);

		glBegin(GL_POLYGON); //begin drawing of polygon
		for (int i = 0; i < shape->GetVertexCount(); i++) {
				glTexCoord2d(texCoordsVec[i].x, texCoordsVec[i].y);
			glVertex2f(floor(points[i].x * M2P), floor(points[i].y * M2P));
		}
		glEnd(); //end drawing of polygon
		glPopMatrix();
	}

}
<|endoftext|>


<commit_before>#include <blackhole/sink/elasticsearch.hpp>
#include <blackhole/utils/atomic.hpp>

#include "../global.hpp"

using namespace blackhole;

TEST(elasticsearch_t, Class) {
    using blackhole::sink::elasticsearch_t;
    elasticsearch_t sink;
    UNUSED(sink);
}

TEST(elasticsearch_t, Manual) {
    using blackhole::sink::elasticsearch_t;
    elasticsearch_t sink;
    std::string msg = "{}";
    boost::algorithm::replace_all(msg, "'", "\"");
    for (int i = 0; i < 200; ++i) {
        sink.consume(msg);
    }
}

using namespace elasticsearch;

namespace mock {

class logger_t {
public:
    template<typename... Args>
    log::record_t open_record(Args&&...) const {
        return log::record_t();
    }

    void push(log::record_t&&) const {}
};

class response_t {
};

class action_t {
public:
    typedef response_t response_type;
    typedef result_t<response_type>::type result_type;

    static const request::method_t method_value = request::method_t::get;

    static const char* name() {
        return "mock.action";
    }

    std::string path() const {
        return "/";
    }
};

class connection_t {
public:
    typedef boost::asio::ip::tcp protocol_type;
    typedef protocol_type::endpoint endpoint_type;

    template<class... Args>
    connection_t(Args&&...) {}

    MOCK_CONST_METHOD0(endpoint, endpoint_type());

    MOCK_METHOD3(perform, void(
        actions::nodes_info_t,
        callback<actions::nodes_info_t>::type,
        long
    ));

    MOCK_METHOD3(perform, void(
        action_t,
        callback<action_t>::type,
        long
    ));
};

class pool_t {
public:
    typedef connection_t connection_type;
    typedef connection_type::endpoint_type endpoint_type;
    typedef std::unordered_map<
        endpoint_type,
        std::shared_ptr<connection_type>
    > pool_type;
    typedef pool_type::size_type size_type;
    typedef pool_type::iterator iterator;

    typedef std::mutex mutex_type;
    typedef pool_lock_t<pool_t> pool_lock_type;

    mutable std::mutex mutex;

    typedef std::pair<iterator, bool> pair_type;
    MOCK_METHOD2(insert, pair_type(
        const endpoint_type&,
        const std::shared_ptr<connection_type>&
    ));
    MOCK_METHOD1(remove, void(const endpoint_type&));

    //!@note: These methods are pure stubs, they shouldn't be called ever.
    MOCK_CONST_METHOD1(size, size_type(pool_lock_type&));
    MOCK_CONST_METHOD1(empty, bool(pool_lock_type&));
    MOCK_METHOD1(begin, iterator(pool_lock_type&));
    MOCK_METHOD1(end, iterator(pool_lock_type&));
};

class balancer : public balancing::strategy<pool_t> {
public:
    typedef pool_t pool_type;
    typedef pool_type::connection_type connection_type;

    MOCK_METHOD1(next, std::shared_ptr<connection_type>(pool_type& pool));
};

} // namespace mock

namespace elasticsearch {

template<>
struct extractor_t<mock::response_t> {
    static mock::response_t extract(const rapidjson::Value&) {
        return mock::response_t();
    }
};

} // namespace elasticsearch

class transport_t_SuccessfullyHandleMessage_Test;

namespace inspector {

//!@note: Helper class to easy ancestor's mock fields inspection.
template<class Connection, class Pool>
class http_transport_t : public elasticsearch::http_transport_t<Connection, Pool> {
    friend class ::transport_t_SuccessfullyHandleMessage_Test;

public:
    template<typename... Args>
    http_transport_t(Args&&... args) :
        elasticsearch::http_transport_t<Connection, Pool>(std::forward<Args>(args)...)
    {}
};

} // namespace inspector

template<class Action>
struct event_t {
    std::atomic<int>& counter;

    void operator()(typename Action::result_type) {
        counter++;
    }
};

void post(boost::asio::io_service& loop,
          callback<mock::action_t>::type callback,
          result_t<mock::response_t>::type result) {
    loop.post(std::bind(callback, result));
}

namespace stub {

synchronized<logger_base_t> log(logger_factory_t::create());

} // namespace stub

TEST(transport_t, SuccessfullyHandleMessage) {
    boost::asio::io_service loop;

    std::unique_ptr<mock::balancer> balancer(new mock::balancer);
    std::shared_ptr<mock::connection_t> connection(new mock::connection_t);

    settings_t settings;
    inspector::http_transport_t<
        mock::connection_t,
        mock::pool_t
    > transport(settings, loop, stub::log);

    EXPECT_CALL(*balancer, next(_))
            .Times(1)
            .WillOnce(Return(connection));
    EXPECT_CALL(*connection, endpoint())
            .WillOnce(Return(mock::connection_t::endpoint_type()));
    EXPECT_CALL(*connection, perform(An<mock::action_t>(), _, _))
            .Times(1)
            .WillOnce(
                WithArg<1>(
                    Invoke(
                        std::bind(
                            &post,
                            std::ref(loop),
                            std::placeholders::_1,
                            mock::response_t()
                        )
                    )
                )
            );

    transport.balancer = std::move(balancer);

    std::atomic<int> counter(0);
    transport.perform(mock::action_t(), event_t<mock::action_t> { counter });
    loop.run_one();

    EXPECT_EQ(1, counter);
}
<commit_msg>[Unit Testing] Added test that checks code sequence after some generic elasticsearch error occurs.<commit_after>#include <blackhole/sink/elasticsearch.hpp>
#include <blackhole/utils/atomic.hpp>

#include "../global.hpp"

using namespace blackhole;

TEST(elasticsearch_t, Class) {
    using blackhole::sink::elasticsearch_t;
    elasticsearch_t sink;
    UNUSED(sink);
}

TEST(elasticsearch_t, Manual) {
    using blackhole::sink::elasticsearch_t;
    elasticsearch_t sink;
    std::string msg = "{}";
    boost::algorithm::replace_all(msg, "'", "\"");
    for (int i = 0; i < 200; ++i) {
        sink.consume(msg);
    }
}

using namespace elasticsearch;

namespace mock {

class logger_t {
public:
    template<typename... Args>
    log::record_t open_record(Args&&...) const {
        return log::record_t();
    }

    void push(log::record_t&&) const {}
};

class response_t {
};

class action_t {
public:
    typedef response_t response_type;
    typedef result_t<response_type>::type result_type;

    static const request::method_t method_value = request::method_t::get;

    static const char* name() {
        return "mock.action";
    }

    std::string path() const {
        return "/";
    }
};

class connection_t {
public:
    typedef boost::asio::ip::tcp protocol_type;
    typedef protocol_type::endpoint endpoint_type;

    template<class... Args>
    connection_t(Args&&...) {}

    MOCK_CONST_METHOD0(endpoint, endpoint_type());

    MOCK_METHOD3(perform, void(
        actions::nodes_info_t,
        callback<actions::nodes_info_t>::type,
        long
    ));

    MOCK_METHOD3(perform, void(
        action_t,
        callback<action_t>::type,
        long
    ));
};

class pool_t {
public:
    typedef connection_t connection_type;
    typedef connection_type::endpoint_type endpoint_type;
    typedef std::unordered_map<
        endpoint_type,
        std::shared_ptr<connection_type>
    > pool_type;
    typedef pool_type::size_type size_type;
    typedef pool_type::iterator iterator;

    typedef std::mutex mutex_type;
    typedef pool_lock_t<pool_t> pool_lock_type;

    mutable std::mutex mutex;

    typedef std::pair<iterator, bool> pair_type;
    MOCK_METHOD2(insert, pair_type(
        const endpoint_type&,
        const std::shared_ptr<connection_type>&
    ));
    MOCK_METHOD1(remove, void(const endpoint_type&));

    //!@note: These methods are pure stubs, they shouldn't be called ever.
    MOCK_CONST_METHOD1(size, size_type(pool_lock_type&));
    MOCK_CONST_METHOD1(empty, bool(pool_lock_type&));
    MOCK_METHOD1(begin, iterator(pool_lock_type&));
    MOCK_METHOD1(end, iterator(pool_lock_type&));
};

class balancer : public balancing::strategy<pool_t> {
public:
    typedef pool_t pool_type;
    typedef pool_type::connection_type connection_type;

    MOCK_METHOD1(next, std::shared_ptr<connection_type>(pool_type& pool));
};

} // namespace mock

namespace elasticsearch {

template<>
struct extractor_t<mock::response_t> {
    static mock::response_t extract(const rapidjson::Value&) {
        return mock::response_t();
    }
};

} // namespace elasticsearch

class transport_t_SuccessfullyHandleMessage_Test;
class transport_t_HandleGenericError_Test;

namespace inspector {

//!@note: Helper class to easy ancestor's mock fields inspection.
template<class Connection, class Pool>
class http_transport_t : public elasticsearch::http_transport_t<Connection, Pool> {
    friend class ::transport_t_SuccessfullyHandleMessage_Test;
    friend class ::transport_t_HandleGenericError_Test;

public:
    template<typename... Args>
    http_transport_t(Args&&... args) :
        elasticsearch::http_transport_t<Connection, Pool>(std::forward<Args>(args)...)
    {}
};

} // namespace inspector

template<class Action>
struct event_t {
    std::atomic<int>& counter;

    void operator()(typename Action::result_type) {
        counter++;
    }
};

void post(boost::asio::io_service& loop,
          callback<mock::action_t>::type callback,
          result_t<mock::response_t>::type result) {
    loop.post(std::bind(callback, result));
}

namespace stub {

synchronized<logger_base_t> log(logger_factory_t::create());

} // namespace stub

TEST(transport_t, SuccessfullyHandleMessage) {
    boost::asio::io_service loop;

    std::unique_ptr<mock::balancer> balancer(new mock::balancer);
    std::shared_ptr<mock::connection_t> connection(new mock::connection_t);

    settings_t settings;
    inspector::http_transport_t<
        mock::connection_t,
        mock::pool_t
    > transport(settings, loop, stub::log);

    EXPECT_CALL(*balancer, next(_))
            .Times(1)
            .WillOnce(Return(connection));
    EXPECT_CALL(*connection, endpoint())
            .WillOnce(Return(mock::connection_t::endpoint_type()));
    EXPECT_CALL(*connection, perform(An<mock::action_t>(), _, _))
            .Times(1)
            .WillOnce(
                WithArg<1>(
                    Invoke(
                        std::bind(
                            &post,
                            std::ref(loop),
                            std::placeholders::_1,
                            mock::response_t()
                        )
                    )
                )
            );

    transport.balancer = std::move(balancer);

    std::atomic<int> counter(0);
    transport.perform(mock::action_t(), event_t<mock::action_t> { counter });
    loop.run_one();

    EXPECT_EQ(1, counter);
}

TEST(transport_t, HandleGenericError) {
    //! After receiving the response with some elasticsearch error,
    //! a caller's callback must be called during next event loop tick.

    boost::asio::io_service loop;

    std::unique_ptr<mock::balancer> balancer(new mock::balancer);
    std::shared_ptr<mock::connection_t> connection(new mock::connection_t);

    settings_t settings;
    inspector::http_transport_t<
        mock::connection_t,
        mock::pool_t
    > transport(settings, loop, stub::log);

    EXPECT_CALL(*balancer, next(_))
            .Times(1)
            .WillOnce(Return(connection));
    EXPECT_CALL(*connection, endpoint())
            .WillOnce(Return(mock::connection_t::endpoint_type()));
    EXPECT_CALL(*connection, perform(An<mock::action_t>(), _, _))
            .Times(1)
            .WillOnce(
                WithArg<1>(
                    Invoke(
                        std::bind(
                            &post,
                            std::ref(loop),
                            std::placeholders::_1,
                            elasticsearch::error_t(generic_error_t("mock"))
                        )
                    )
                )
            );

    transport.balancer = std::move(balancer);

    std::atomic<int> counter(0);
    transport.perform(mock::action_t(), event_t<mock::action_t> { counter });
    loop.run_one();

    EXPECT_EQ(1, counter);
}
<|endoftext|>


<commit_before>/*
QWebSockets implements the WebSocket protocol as defined in RFC 6455.
Copyright (C) 2013 Kurt Pattyn (pattyn.kurt@gmail.com)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "handshakerequest_p.h"
#include <QString>
#include <QMap>
#include <QTextStream>
#include <QUrl>
#include <QList>
#include <QStringList>
#include "qwebsocketprotocol.h"

QT_BEGIN_NAMESPACE

/*!
    \internal
 */
HandshakeRequest::HandshakeRequest(int port, bool isSecure) :
    m_port(port),
    m_isSecure(isSecure),
    m_isValid(false),
    m_headers(),
    m_versions(),
    m_key(),
    m_origin(),
    m_protocols(),
    m_extensions(),
    m_requestUrl()
{
}

/*!
    \internal
 */
HandshakeRequest::~HandshakeRequest()
{
}

/*!
    \internal
 */
void HandshakeRequest::clear()
{
    m_port = -1;
    m_isSecure = false;
    m_isValid = false;
    m_headers.clear();
    m_versions.clear();
    m_key.clear();
    m_origin.clear();
    m_protocols.clear();
    m_extensions.clear();
    m_requestUrl.clear();
}

/*!
    \internal
 */
int HandshakeRequest::getPort() const
{
    return m_requestUrl.port(m_port);
}

/*!
    \internal
 */
bool HandshakeRequest::isSecure() const
{
    return m_isSecure;
}

/*!
    \internal
 */
bool HandshakeRequest::isValid() const
{
    return m_isValid;
}

/*!
    \internal
 */
QMap<QString, QString> HandshakeRequest::getHeaders() const
{
    return m_headers;
}

/*!
    \internal
 */
QList<QWebSocketProtocol::Version> HandshakeRequest::getVersions() const
{
    return m_versions;
}

/*!
    \internal
 */
QString HandshakeRequest::getResourceName() const
{
    return m_requestUrl.path();
}

/*!
    \internal
 */
QString HandshakeRequest::getKey() const
{
    return m_key;
}

/*!
    \internal
 */
QString HandshakeRequest::getHost() const
{
    return m_requestUrl.host();
}

/*!
    \internal
 */
QString HandshakeRequest::getOrigin() const
{
    return m_origin;
}

/*!
    \internal
 */
QList<QString> HandshakeRequest::getProtocols() const
{
    return m_protocols;
}

/*!
    \internal
 */
QList<QString> HandshakeRequest::getExtensions() const
{
    return m_extensions;
}

/*!
    \internal
 */
QUrl HandshakeRequest::getRequestUrl() const
{
    return m_requestUrl;
}

/*!
    \internal
 */
QTextStream &HandshakeRequest::readFromStream(QTextStream &textStream)
{
    m_isValid = false;
    clear();
    if (textStream.status() == QTextStream::Ok)
    {
        QString requestLine = textStream.readLine();
        QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts);
        QString verb = tokens[0];
        QString resourceName = tokens[1];
        QString httpProtocol = tokens[2];
        bool conversionOk = false;
        float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk);

        QString headerLine = textStream.readLine();
        m_headers.clear();
        while (!headerLine.isEmpty())
        {
            QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
            m_headers.insertMulti(headerField[0], headerField[1]);
            headerLine = textStream.readLine();
        }

        QString host = m_headers.value("Host", "");
        m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1());
        if (m_requestUrl.isRelative())
        {
            m_requestUrl.setHost(host);
        }
        if (m_requestUrl.scheme().isEmpty())
        {
            QString scheme =  isSecure() ? "wss://" : "ws://";
            m_requestUrl.setScheme(scheme);
        }

        QStringList versionLines = m_headers.values("Sec-WebSocket-Version");
        Q_FOREACH(QString versionLine, versionLines)
        {
            QStringList versions = versionLine.split(",", QString::SkipEmptyParts);
            Q_FOREACH(QString version, versions)
            {
                QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString(version.trimmed());
                m_versions << ver;
            }
        }
        qStableSort(m_versions.begin(), m_versions.end(), qGreater<QWebSocketProtocol::Version>());	//sort in descending order
        m_key = m_headers.value("Sec-WebSocket-Key", "");
        QString upgrade = m_headers.value("Upgrade", ""); //must be equal to "websocket", case-insensitive
        QString connection = m_headers.value("Connection", "");	//must contain "Upgrade", case-insensitive
        QStringList connectionLine = connection.split(",", QString::SkipEmptyParts);
        QStringList connectionValues;
        Q_FOREACH(QString connection, connectionLine)
        {
            connectionValues << connection.trimmed();
        }

        //optional headers
        m_origin = m_headers.value("Sec-WebSocket-Origin", "");
        QStringList protocolLines = m_headers.values("Sec-WebSocket-Protocol");
        Q_FOREACH(QString protocolLine, protocolLines)
        {
            QStringList protocols = protocolLine.split(",", QString::SkipEmptyParts);
            Q_FOREACH(QString protocol, protocols)
            {
                m_protocols << protocol.trimmed();
            }
        }
        QStringList extensionLines = m_headers.values("Sec-WebSocket-Extensions");
        Q_FOREACH(QString extensionLine, extensionLines)
        {
            QStringList extensions = extensionLine.split(",", QString::SkipEmptyParts);
            Q_FOREACH(QString extension, extensions)
            {
                m_extensions << extension.trimmed();
            }
        }
        //TODO: authentication field

        m_isValid = !(host.isEmpty() ||
                      resourceName.isEmpty() ||
                      m_versions.isEmpty() ||
                      m_key.isEmpty() ||
                      (verb != "GET") ||
                      (!conversionOk || (httpVersion < 1.1f)) ||
                      (upgrade.toLower() != "websocket") ||
                      (!connectionValues.contains("upgrade", Qt::CaseInsensitive)));
    }
    return textStream;
}

/*!
    \internal
 */
QTextStream &operator >>(QTextStream &stream, HandshakeRequest &request)
{
    return request.readFromStream(stream);
}

QT_END_NAMESPACE
<commit_msg>Replace string literals with QString::fromLatin1() expression, to avoid deprecated warning (since Qt 5.1.1)<commit_after>/*
QWebSockets implements the WebSocket protocol as defined in RFC 6455.
Copyright (C) 2013 Kurt Pattyn (pattyn.kurt@gmail.com)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "handshakerequest_p.h"
#include <QString>
#include <QMap>
#include <QTextStream>
#include <QUrl>
#include <QList>
#include <QStringList>
#include "qwebsocketprotocol.h"

QT_BEGIN_NAMESPACE

/*!
    \internal
 */
HandshakeRequest::HandshakeRequest(int port, bool isSecure) :
    m_port(port),
    m_isSecure(isSecure),
    m_isValid(false),
    m_headers(),
    m_versions(),
    m_key(),
    m_origin(),
    m_protocols(),
    m_extensions(),
    m_requestUrl()
{
}

/*!
    \internal
 */
HandshakeRequest::~HandshakeRequest()
{
}

/*!
    \internal
 */
void HandshakeRequest::clear()
{
    m_port = -1;
    m_isSecure = false;
    m_isValid = false;
    m_headers.clear();
    m_versions.clear();
    m_key.clear();
    m_origin.clear();
    m_protocols.clear();
    m_extensions.clear();
    m_requestUrl.clear();
}

/*!
    \internal
 */
int HandshakeRequest::getPort() const
{
    return m_requestUrl.port(m_port);
}

/*!
    \internal
 */
bool HandshakeRequest::isSecure() const
{
    return m_isSecure;
}

/*!
    \internal
 */
bool HandshakeRequest::isValid() const
{
    return m_isValid;
}

/*!
    \internal
 */
QMap<QString, QString> HandshakeRequest::getHeaders() const
{
    return m_headers;
}

/*!
    \internal
 */
QList<QWebSocketProtocol::Version> HandshakeRequest::getVersions() const
{
    return m_versions;
}

/*!
    \internal
 */
QString HandshakeRequest::getResourceName() const
{
    return m_requestUrl.path();
}

/*!
    \internal
 */
QString HandshakeRequest::getKey() const
{
    return m_key;
}

/*!
    \internal
 */
QString HandshakeRequest::getHost() const
{
    return m_requestUrl.host();
}

/*!
    \internal
 */
QString HandshakeRequest::getOrigin() const
{
    return m_origin;
}

/*!
    \internal
 */
QList<QString> HandshakeRequest::getProtocols() const
{
    return m_protocols;
}

/*!
    \internal
 */
QList<QString> HandshakeRequest::getExtensions() const
{
    return m_extensions;
}

/*!
    \internal
 */
QUrl HandshakeRequest::getRequestUrl() const
{
    return m_requestUrl;
}

/*!
    \internal
 */
QTextStream &HandshakeRequest::readFromStream(QTextStream &textStream)
{
    m_isValid = false;
    clear();
    if (textStream.status() == QTextStream::Ok)
    {
        QString requestLine = textStream.readLine();
        QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts);
        QString verb = tokens[0];
        QString resourceName = tokens[1];
        QString httpProtocol = tokens[2];
        bool conversionOk = false;
        float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk);

        QString headerLine = textStream.readLine();
        m_headers.clear();
        while (!headerLine.isEmpty())
        {
            QStringList headerField = headerLine.split(QString::fromLatin1(": "), QString::SkipEmptyParts);
            m_headers.insertMulti(headerField[0], headerField[1]);
            headerLine = textStream.readLine();
        }

        QString host = m_headers.value("Host", "");
        m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1());
        if (m_requestUrl.isRelative())
        {
            m_requestUrl.setHost(host);
        }
        if (m_requestUrl.scheme().isEmpty())
        {
            QString scheme =  QString::fromLatin1(isSecure() ? "wss://" : "ws://");
            m_requestUrl.setScheme(scheme);
        }

        QStringList versionLines = m_headers.values("Sec-WebSocket-Version");
        Q_FOREACH(QString versionLine, versionLines)
        {
            QStringList versions = versionLine.split(",", QString::SkipEmptyParts);
            Q_FOREACH(QString version, versions)
            {
                QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString(version.trimmed());
                m_versions << ver;
            }
        }
        qStableSort(m_versions.begin(), m_versions.end(), qGreater<QWebSocketProtocol::Version>());	//sort in descending order
        m_key = m_headers.value("Sec-WebSocket-Key", "");
        QString upgrade = m_headers.value("Upgrade", ""); //must be equal to "websocket", case-insensitive
        QString connection = m_headers.value("Connection", "");	//must contain "Upgrade", case-insensitive
        QStringList connectionLine = connection.split(",", QString::SkipEmptyParts);
        QStringList connectionValues;
        Q_FOREACH(QString connection, connectionLine)
        {
            connectionValues << connection.trimmed();
        }

        //optional headers
        m_origin = m_headers.value("Sec-WebSocket-Origin", "");
        QStringList protocolLines = m_headers.values("Sec-WebSocket-Protocol");
        Q_FOREACH(QString protocolLine, protocolLines)
        {
            QStringList protocols = protocolLine.split(",", QString::SkipEmptyParts);
            Q_FOREACH(QString protocol, protocols)
            {
                m_protocols << protocol.trimmed();
            }
        }
        QStringList extensionLines = m_headers.values("Sec-WebSocket-Extensions");
        Q_FOREACH(QString extensionLine, extensionLines)
        {
            QStringList extensions = extensionLine.split(",", QString::SkipEmptyParts);
            Q_FOREACH(QString extension, extensions)
            {
                m_extensions << extension.trimmed();
            }
        }
        //TODO: authentication field

        m_isValid = !(host.isEmpty() ||
                      resourceName.isEmpty() ||
                      m_versions.isEmpty() ||
                      m_key.isEmpty() ||
                      (verb != QString::fromLatin1("GET")) ||
                      (!conversionOk || (httpVersion < 1.1f)) ||
                      (upgrade.toLower() != QString::fromLatin1("websocket")) ||
                      (!connectionValues.contains("upgrade", Qt::CaseInsensitive)));
    }
    return textStream;
}

/*!
    \internal
 */
QTextStream &operator >>(QTextStream &stream, HandshakeRequest &request)
{
    return request.readFromStream(stream);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <gflags/gflags.h>

#include <cinttypes>
#include <cstring>
#include <string>
#include <vector>

#include "xenia/base/logging.h"
#include "xenia/base/main.h"
#include "xenia/base/platform.h"
#include "xenia/base/string.h"
#include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/glsl_shader_translator.h"
#include "xenia/gpu/shader_translator.h"
#include "xenia/gpu/spirv_shader_translator.h"
#include "xenia/ui/spirv/spirv_disassembler.h"

// For D3DDisassemble:
#if XE_PLATFORM_WIN32
#include "xenia/ui/d3d12/d3d12_api.h"
#endif  // XE_PLATFORM_WIN32

DEFINE_string(shader_input, "", "Input shader binary file path.");
DEFINE_string(shader_input_type, "",
              "'vs', 'ps', or unspecified to infer from the given filename.");
DEFINE_string(shader_output, "", "Output shader file path.");
DEFINE_string(shader_output_type, "ucode",
              "Translator to use: [ucode, glsl45, spirv, spirvtext, dxbc].");
DEFINE_string(shader_output_patch, "",
              "Tessellation patch type in the generated tessellation "
              "evaluation (domain) shader, or unspecified to produce a vertex "
              "shader: [line, triangle, quad].");
DEFINE_bool(shader_output_dxbc_rov, false,
            "Output ROV-based output-merger code in DXBC pixel shaders.");

namespace xe {
namespace gpu {

int shader_compiler_main(const std::vector<std::wstring>& args) {
  ShaderType shader_type;
  if (!FLAGS_shader_input_type.empty()) {
    if (FLAGS_shader_input_type == "vs") {
      shader_type = ShaderType::kVertex;
    } else if (FLAGS_shader_input_type == "ps") {
      shader_type = ShaderType::kPixel;
    } else {
      XELOGE("Invalid --shader_input_type; must be 'vs' or 'ps'.");
      return 1;
    }
  } else {
    auto last_dot = FLAGS_shader_input.find_last_of('.');
    bool valid_type = false;
    if (last_dot != std::string::npos) {
      if (FLAGS_shader_input.substr(last_dot) == ".vs") {
        shader_type = ShaderType::kVertex;
        valid_type = true;
      } else if (FLAGS_shader_input.substr(last_dot) == ".ps") {
        shader_type = ShaderType::kPixel;
        valid_type = true;
      }
    }
    if (!valid_type) {
      XELOGE(
          "File type not recognized (use .vs, .ps or "
          "--shader_input_type=vs|ps).");
      return 1;
    }
  }

  auto input_file = fopen(FLAGS_shader_input.c_str(), "rb");
  if (!input_file) {
    XELOGE("Unable to open input file: %s", FLAGS_shader_input.c_str());
    return 1;
  }
  fseek(input_file, 0, SEEK_END);
  size_t input_file_size = ftell(input_file);
  fseek(input_file, 0, SEEK_SET);
  std::vector<uint32_t> ucode_dwords(input_file_size / 4);
  fread(ucode_dwords.data(), 4, ucode_dwords.size(), input_file);
  fclose(input_file);

  XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).",
         FLAGS_shader_input.c_str(),
         shader_type == ShaderType::kVertex ? "vertex" : "pixel",
         ucode_dwords.size(), ucode_dwords.size() * 4);

  // TODO(benvanik): hash? need to return the data to big-endian format first.
  uint64_t ucode_data_hash = 0;
  auto shader = std::make_unique<Shader>(
      shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size());

  std::unique_ptr<ShaderTranslator> translator;
  if (FLAGS_shader_output_type == "spirv" ||
      FLAGS_shader_output_type == "spirvtext") {
    translator = std::make_unique<SpirvShaderTranslator>();
  } else if (FLAGS_shader_output_type == "glsl45") {
    translator = std::make_unique<GlslShaderTranslator>(
        GlslShaderTranslator::Dialect::kGL45);
  } else if (FLAGS_shader_output_type == "dxbc") {
    translator =
        std::make_unique<DxbcShaderTranslator>(0, FLAGS_shader_output_dxbc_rov);
  } else {
    translator = std::make_unique<UcodeShaderTranslator>();
  }

  PrimitiveType patch_primitive_type = PrimitiveType::kNone;
  if (shader_type == ShaderType::kVertex) {
    if (FLAGS_shader_output_patch == "line") {
      patch_primitive_type == PrimitiveType::kLinePatch;
    } else if (FLAGS_shader_output_patch == "triangle") {
      patch_primitive_type == PrimitiveType::kTrianglePatch;
    } else if (FLAGS_shader_output_patch == "quad") {
      patch_primitive_type == PrimitiveType::kQuadPatch;
    }
  }

  translator->Translate(shader.get(), patch_primitive_type);

  const void* source_data = shader->translated_binary().data();
  size_t source_data_size = shader->translated_binary().size();

  std::unique_ptr<xe::ui::spirv::SpirvDisassembler::Result> spirv_disasm_result;
  if (FLAGS_shader_output_type == "spirvtext") {
    // Disassemble SPIRV.
    spirv_disasm_result = xe::ui::spirv::SpirvDisassembler().Disassemble(
        reinterpret_cast<const uint32_t*>(source_data), source_data_size / 4);
    source_data = spirv_disasm_result->text();
    source_data_size = std::strlen(spirv_disasm_result->text()) + 1;
  }
#if XE_PLATFORM_WIN32
  ID3DBlob* dxbc_disasm_blob = nullptr;
  if (FLAGS_shader_output_type == "dxbc") {
    HMODULE d3d_compiler = LoadLibrary(L"D3DCompiler_47.dll");
    if (d3d_compiler != nullptr) {
      pD3DDisassemble d3d_disassemble =
          pD3DDisassemble(GetProcAddress(d3d_compiler, "D3DDisassemble"));
      if (d3d_disassemble != nullptr) {
        // Disassemble DXBC.
        if (SUCCEEDED(d3d_disassemble(source_data, source_data_size,
                                      D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING |
                                          D3D_DISASM_ENABLE_INSTRUCTION_OFFSET,
                                      nullptr, &dxbc_disasm_blob))) {
          source_data = dxbc_disasm_blob->GetBufferPointer();
          source_data_size = dxbc_disasm_blob->GetBufferSize();
        }
      }
      FreeLibrary(d3d_compiler);
    }
  }
#endif  // XE_PLATFORM_WIN32

  if (!FLAGS_shader_output.empty()) {
    auto output_file = fopen(FLAGS_shader_output.c_str(), "wb");
    fwrite(source_data, 1, source_data_size, output_file);
    fclose(output_file);
  }

#if XE_PLATFORM_WIN32
  if (dxbc_disasm_blob != nullptr) {
    dxbc_disasm_blob->Release();
  }
#endif  // XE_PLATFORM_WIN32

  return 0;
}

}  // namespace gpu
}  // namespace xe

DEFINE_ENTRY_POINT(L"xenia-gpu-shader-compiler",
                   L"xenia-gpu-shader-compiler shader.bin",
                   xe::gpu::shader_compiler_main);
<commit_msg>[D3D12] Fix typos in shader_compiler_main<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <gflags/gflags.h>

#include <cinttypes>
#include <cstring>
#include <string>
#include <vector>

#include "xenia/base/logging.h"
#include "xenia/base/main.h"
#include "xenia/base/platform.h"
#include "xenia/base/string.h"
#include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/glsl_shader_translator.h"
#include "xenia/gpu/shader_translator.h"
#include "xenia/gpu/spirv_shader_translator.h"
#include "xenia/ui/spirv/spirv_disassembler.h"

// For D3DDisassemble:
#if XE_PLATFORM_WIN32
#include "xenia/ui/d3d12/d3d12_api.h"
#endif  // XE_PLATFORM_WIN32

DEFINE_string(shader_input, "", "Input shader binary file path.");
DEFINE_string(shader_input_type, "",
              "'vs', 'ps', or unspecified to infer from the given filename.");
DEFINE_string(shader_output, "", "Output shader file path.");
DEFINE_string(shader_output_type, "ucode",
              "Translator to use: [ucode, glsl45, spirv, spirvtext, dxbc].");
DEFINE_string(shader_output_patch, "",
              "Tessellation patch type in the generated tessellation "
              "evaluation (domain) shader, or unspecified to produce a vertex "
              "shader: [line, triangle, quad].");
DEFINE_bool(shader_output_dxbc_rov, false,
            "Output ROV-based output-merger code in DXBC pixel shaders.");

namespace xe {
namespace gpu {

int shader_compiler_main(const std::vector<std::wstring>& args) {
  ShaderType shader_type;
  if (!FLAGS_shader_input_type.empty()) {
    if (FLAGS_shader_input_type == "vs") {
      shader_type = ShaderType::kVertex;
    } else if (FLAGS_shader_input_type == "ps") {
      shader_type = ShaderType::kPixel;
    } else {
      XELOGE("Invalid --shader_input_type; must be 'vs' or 'ps'.");
      return 1;
    }
  } else {
    auto last_dot = FLAGS_shader_input.find_last_of('.');
    bool valid_type = false;
    if (last_dot != std::string::npos) {
      if (FLAGS_shader_input.substr(last_dot) == ".vs") {
        shader_type = ShaderType::kVertex;
        valid_type = true;
      } else if (FLAGS_shader_input.substr(last_dot) == ".ps") {
        shader_type = ShaderType::kPixel;
        valid_type = true;
      }
    }
    if (!valid_type) {
      XELOGE(
          "File type not recognized (use .vs, .ps or "
          "--shader_input_type=vs|ps).");
      return 1;
    }
  }

  auto input_file = fopen(FLAGS_shader_input.c_str(), "rb");
  if (!input_file) {
    XELOGE("Unable to open input file: %s", FLAGS_shader_input.c_str());
    return 1;
  }
  fseek(input_file, 0, SEEK_END);
  size_t input_file_size = ftell(input_file);
  fseek(input_file, 0, SEEK_SET);
  std::vector<uint32_t> ucode_dwords(input_file_size / 4);
  fread(ucode_dwords.data(), 4, ucode_dwords.size(), input_file);
  fclose(input_file);

  XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).",
         FLAGS_shader_input.c_str(),
         shader_type == ShaderType::kVertex ? "vertex" : "pixel",
         ucode_dwords.size(), ucode_dwords.size() * 4);

  // TODO(benvanik): hash? need to return the data to big-endian format first.
  uint64_t ucode_data_hash = 0;
  auto shader = std::make_unique<Shader>(
      shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size());

  std::unique_ptr<ShaderTranslator> translator;
  if (FLAGS_shader_output_type == "spirv" ||
      FLAGS_shader_output_type == "spirvtext") {
    translator = std::make_unique<SpirvShaderTranslator>();
  } else if (FLAGS_shader_output_type == "glsl45") {
    translator = std::make_unique<GlslShaderTranslator>(
        GlslShaderTranslator::Dialect::kGL45);
  } else if (FLAGS_shader_output_type == "dxbc") {
    translator =
        std::make_unique<DxbcShaderTranslator>(0, FLAGS_shader_output_dxbc_rov);
  } else {
    translator = std::make_unique<UcodeShaderTranslator>();
  }

  PrimitiveType patch_primitive_type = PrimitiveType::kNone;
  if (shader_type == ShaderType::kVertex) {
    if (FLAGS_shader_output_patch == "line") {
      patch_primitive_type = PrimitiveType::kLinePatch;
    } else if (FLAGS_shader_output_patch == "triangle") {
      patch_primitive_type = PrimitiveType::kTrianglePatch;
    } else if (FLAGS_shader_output_patch == "quad") {
      patch_primitive_type = PrimitiveType::kQuadPatch;
    }
  }

  translator->Translate(shader.get(), patch_primitive_type);

  const void* source_data = shader->translated_binary().data();
  size_t source_data_size = shader->translated_binary().size();

  std::unique_ptr<xe::ui::spirv::SpirvDisassembler::Result> spirv_disasm_result;
  if (FLAGS_shader_output_type == "spirvtext") {
    // Disassemble SPIRV.
    spirv_disasm_result = xe::ui::spirv::SpirvDisassembler().Disassemble(
        reinterpret_cast<const uint32_t*>(source_data), source_data_size / 4);
    source_data = spirv_disasm_result->text();
    source_data_size = std::strlen(spirv_disasm_result->text()) + 1;
  }
#if XE_PLATFORM_WIN32
  ID3DBlob* dxbc_disasm_blob = nullptr;
  if (FLAGS_shader_output_type == "dxbc") {
    HMODULE d3d_compiler = LoadLibrary(L"D3DCompiler_47.dll");
    if (d3d_compiler != nullptr) {
      pD3DDisassemble d3d_disassemble =
          pD3DDisassemble(GetProcAddress(d3d_compiler, "D3DDisassemble"));
      if (d3d_disassemble != nullptr) {
        // Disassemble DXBC.
        if (SUCCEEDED(d3d_disassemble(source_data, source_data_size,
                                      D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING |
                                          D3D_DISASM_ENABLE_INSTRUCTION_OFFSET,
                                      nullptr, &dxbc_disasm_blob))) {
          source_data = dxbc_disasm_blob->GetBufferPointer();
          source_data_size = dxbc_disasm_blob->GetBufferSize();
        }
      }
      FreeLibrary(d3d_compiler);
    }
  }
#endif  // XE_PLATFORM_WIN32

  if (!FLAGS_shader_output.empty()) {
    auto output_file = fopen(FLAGS_shader_output.c_str(), "wb");
    fwrite(source_data, 1, source_data_size, output_file);
    fclose(output_file);
  }

#if XE_PLATFORM_WIN32
  if (dxbc_disasm_blob != nullptr) {
    dxbc_disasm_blob->Release();
  }
#endif  // XE_PLATFORM_WIN32

  return 0;
}

}  // namespace gpu
}  // namespace xe

DEFINE_ENTRY_POINT(L"xenia-gpu-shader-compiler",
                   L"xenia-gpu-shader-compiler shader.bin",
                   xe::gpu::shader_compiler_main);
<|endoftext|>


<commit_before><commit_msg>coverity#1255389 Dereference null return value<commit_after><|endoftext|>


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

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

#pragma hdrstop

#include "swstylemanager.hxx"
#include <hash_map>
#include <svtools/stylepool.hxx>

#ifndef _DOC_HXX
#include <doc.hxx>
#endif

#ifndef _CHARFMT_HXX
#include <charfmt.hxx>
#endif

#ifndef _DOCARY_HXX
#include <docary.hxx>
#endif

#ifndef _SWTYPES_HXX
#include <swtypes.hxx>
#endif

#ifndef _ISTYLEACCESS_HXX
#include <istyleaccess.hxx>
#endif

typedef ::std::hash_map< const ::rtl::OUString,
                         StylePool::SfxItemSet_Pointer_t,
                         ::rtl::OUStringHash,
                         ::std::equal_to< ::rtl::OUString > > SwStyleNameCache;

class SwStyleCache
{
    SwStyleNameCache mMap;
public:
    SwStyleCache() {}
    void addStyleName( StylePool::SfxItemSet_Pointer_t pStyle )
        { mMap[ StylePool::nameOf(pStyle) ] = pStyle; }
    void addCompletePool( StylePool& rPool );
    StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName ) { return mMap[rName]; }
};

void SwStyleCache::addCompletePool( StylePool& rPool )
{
    IStylePoolIteratorAccess *pIter = rPool.createIterator();
    StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
    while( pStyle.get() )
    {
        rtl::OUString aName( StylePool::nameOf(pStyle) );
        mMap[ aName ] = pStyle;
        pStyle = pIter->getNext();
    }
    delete pIter;
}

class SwStyleManager : public IStyleAccess
{
    StylePool aAutoCharPool;
    StylePool aAutoParaPool;
    SwStyleCache *mpCharCache;
    SwStyleCache *mpParaCache;

public:
    SwStyleManager() : mpCharCache(0), mpParaCache(0) {}
    virtual ~SwStyleManager();
    virtual StylePool::SfxItemSet_Pointer_t getAutomaticStyle( const SfxItemSet& rSet,
                                                               IStyleAccess::SwAutoStyleFamily eFamily );
    virtual StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName,
                                                               IStyleAccess::SwAutoStyleFamily eFamily );
    virtual void getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
                                                               IStyleAccess::SwAutoStyleFamily eFamily );
    virtual StylePool::SfxItemSet_Pointer_t cacheAutomaticStyle( const SfxItemSet& rSet,
                                                               SwAutoStyleFamily eFamily );
    virtual void clearCaches();
};

IStyleAccess *createStyleManager()
{
    return new SwStyleManager();
}

SwStyleManager::~SwStyleManager()
{
    delete mpCharCache;
    delete mpParaCache;
}

void SwStyleManager::clearCaches()
{
    delete mpCharCache;
    mpCharCache = 0;
    delete mpParaCache;
    mpParaCache = 0;
}

StylePool::SfxItemSet_Pointer_t SwStyleManager::getAutomaticStyle( const SfxItemSet& rSet,
                                                                   IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    return rAutoPool.insertItemSet( rSet );
}

StylePool::SfxItemSet_Pointer_t SwStyleManager::cacheAutomaticStyle( const SfxItemSet& rSet,
                                                                   IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    StylePool::SfxItemSet_Pointer_t pStyle = rAutoPool.insertItemSet( rSet );
    SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ?
                             mpCharCache : mpParaCache;
    if( !rpCache )
        rpCache = new SwStyleCache();
    rpCache->addStyleName( pStyle );
    return pStyle;
}

StylePool::SfxItemSet_Pointer_t SwStyleManager::getByName( const rtl::OUString& rName,
                                                           IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? mpCharCache : mpParaCache;
    if( !rpCache )
        rpCache = new SwStyleCache();
    StylePool::SfxItemSet_Pointer_t pStyle = rpCache->getByName( rName );
    if( !pStyle.get() )
    {
        // Ok, ok, it's allowed to ask for uncached styles (from UNO) but it should not be done
        // during loading a document
        ASSERT( false, "Don't ask for uncached styles" );
        rpCache->addCompletePool( rAutoPool );
        pStyle = rpCache->getByName( rName );
    }
    return pStyle;
}

void SwStyleManager::getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
                                   IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    IStylePoolIteratorAccess *pIter = rAutoPool.createIterator();
    StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
    while( pStyle.get() )
    {
        // Do not consider styles which aren't used.
        if ( pStyle.use_count() > 2 )
            rStyles.push_back( pStyle );
        pStyle = pIter->getNext();
    }
    delete pIter;
}
<commit_msg>INTEGRATION: CWS mingwport06 (1.3.358); FILE MERGED 2007/08/24 13:25:59 vg 1.3.358.1: #i75499# pragma is for MSVC<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swstylemanager.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2007-09-06 14:00:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifdef _MSC_VER
#pragma hdrstop
#endif

#include "swstylemanager.hxx"
#include <hash_map>
#include <svtools/stylepool.hxx>

#ifndef _DOC_HXX
#include <doc.hxx>
#endif

#ifndef _CHARFMT_HXX
#include <charfmt.hxx>
#endif

#ifndef _DOCARY_HXX
#include <docary.hxx>
#endif

#ifndef _SWTYPES_HXX
#include <swtypes.hxx>
#endif

#ifndef _ISTYLEACCESS_HXX
#include <istyleaccess.hxx>
#endif

typedef ::std::hash_map< const ::rtl::OUString,
                         StylePool::SfxItemSet_Pointer_t,
                         ::rtl::OUStringHash,
                         ::std::equal_to< ::rtl::OUString > > SwStyleNameCache;

class SwStyleCache
{
    SwStyleNameCache mMap;
public:
    SwStyleCache() {}
    void addStyleName( StylePool::SfxItemSet_Pointer_t pStyle )
        { mMap[ StylePool::nameOf(pStyle) ] = pStyle; }
    void addCompletePool( StylePool& rPool );
    StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName ) { return mMap[rName]; }
};

void SwStyleCache::addCompletePool( StylePool& rPool )
{
    IStylePoolIteratorAccess *pIter = rPool.createIterator();
    StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
    while( pStyle.get() )
    {
        rtl::OUString aName( StylePool::nameOf(pStyle) );
        mMap[ aName ] = pStyle;
        pStyle = pIter->getNext();
    }
    delete pIter;
}

class SwStyleManager : public IStyleAccess
{
    StylePool aAutoCharPool;
    StylePool aAutoParaPool;
    SwStyleCache *mpCharCache;
    SwStyleCache *mpParaCache;

public:
    SwStyleManager() : mpCharCache(0), mpParaCache(0) {}
    virtual ~SwStyleManager();
    virtual StylePool::SfxItemSet_Pointer_t getAutomaticStyle( const SfxItemSet& rSet,
                                                               IStyleAccess::SwAutoStyleFamily eFamily );
    virtual StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName,
                                                               IStyleAccess::SwAutoStyleFamily eFamily );
    virtual void getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
                                                               IStyleAccess::SwAutoStyleFamily eFamily );
    virtual StylePool::SfxItemSet_Pointer_t cacheAutomaticStyle( const SfxItemSet& rSet,
                                                               SwAutoStyleFamily eFamily );
    virtual void clearCaches();
};

IStyleAccess *createStyleManager()
{
    return new SwStyleManager();
}

SwStyleManager::~SwStyleManager()
{
    delete mpCharCache;
    delete mpParaCache;
}

void SwStyleManager::clearCaches()
{
    delete mpCharCache;
    mpCharCache = 0;
    delete mpParaCache;
    mpParaCache = 0;
}

StylePool::SfxItemSet_Pointer_t SwStyleManager::getAutomaticStyle( const SfxItemSet& rSet,
                                                                   IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    return rAutoPool.insertItemSet( rSet );
}

StylePool::SfxItemSet_Pointer_t SwStyleManager::cacheAutomaticStyle( const SfxItemSet& rSet,
                                                                   IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    StylePool::SfxItemSet_Pointer_t pStyle = rAutoPool.insertItemSet( rSet );
    SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ?
                             mpCharCache : mpParaCache;
    if( !rpCache )
        rpCache = new SwStyleCache();
    rpCache->addStyleName( pStyle );
    return pStyle;
}

StylePool::SfxItemSet_Pointer_t SwStyleManager::getByName( const rtl::OUString& rName,
                                                           IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? mpCharCache : mpParaCache;
    if( !rpCache )
        rpCache = new SwStyleCache();
    StylePool::SfxItemSet_Pointer_t pStyle = rpCache->getByName( rName );
    if( !pStyle.get() )
    {
        // Ok, ok, it's allowed to ask for uncached styles (from UNO) but it should not be done
        // during loading a document
        ASSERT( false, "Don't ask for uncached styles" );
        rpCache->addCompletePool( rAutoPool );
        pStyle = rpCache->getByName( rName );
    }
    return pStyle;
}

void SwStyleManager::getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
                                   IStyleAccess::SwAutoStyleFamily eFamily )
{
    StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
    IStylePoolIteratorAccess *pIter = rAutoPool.createIterator();
    StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
    while( pStyle.get() )
    {
        // Do not consider styles which aren't used.
        if ( pStyle.use_count() > 2 )
            rStyles.push_back( pStyle );
        pStyle = pIter->getNext();
    }
    delete pIter;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: staticassert.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 06:05:02 $
 *
 *  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
 *
 ************************************************************************/

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
#ifndef WW_STATICASSERT_HXX
#define WW_STATICASSERT_HXX

/*
 Lifted direct from:
 Modern C++ Design: Generic Programming and Design Patterns Applied
 Section 2.1
 by Andrei Alexandrescu
*/
namespace ww
{
    template<bool> class compile_time_check
    {
    public:
        compile_time_check(...) {}
    };

    template<> class compile_time_check<false>
    {
    };
}

    /*
    Similiar to assert, StaticAssert is only in operation when NDEBUG is not
    defined. It will test its first argument at compile time and on failure
    report the error message of the second argument, which must be a valid c++
    classname. i.e. no spaces, punctuation or reserved keywords.
    */
#ifndef NDEBUG
#   define StaticAssert(test, errormsg)                         \
    do {                                                        \
        struct ERROR_##errormsg {};                             \
        typedef ww::compile_time_check< (test) != 0 > tmplimpl; \
        tmplimpl aTemp = tmplimpl(ERROR_##errormsg());          \
        sizeof(aTemp);                                          \
    } while (0)
#else
#   define StaticAssert(test, errormsg)                         \
    do {} while (0)
#endif

#endif
/* vi:set tabstop=4 shiftwidth=4 expandtab: */
<commit_msg>INTEGRATION: CWS thaiissues (1.4.888); FILE MERGED<commit_after>/*************************************************************************
 *
 *  $RCSfile: staticassert.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2005-11-16 09:33:33 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
#ifndef WW_STATICASSERT_HXX
#define WW_STATICASSERT_HXX

/*
 Lifted direct from:
 Modern C++ Design: Generic Programming and Design Patterns Applied
 Section 2.1
 by Andrei Alexandrescu
*/
namespace ww
{
    template<bool> class compile_time_check
    {
    public:
        compile_time_check(...) {}
    };

    template<> class compile_time_check<false>
    {
    };
}

    /*
    Similiar to assert, StaticAssert is only in operation when NDEBUG is not
    defined. It will test its first argument at compile time and on failure
    report the error message of the second argument, which must be a valid c++
    classname. i.e. no spaces, punctuation or reserved keywords.
    */
#ifndef NDEBUG
#   define StaticAssert(test, errormsg)                         \
    do {                                                        \
        struct ERROR_##errormsg {};                             \
        typedef ww::compile_time_check< (test) != 0 > tmplimpl; \
        tmplimpl aTemp = tmplimpl(ERROR_##errormsg());          \
        sizeof(aTemp);                                          \
    } while (0)
#else
#   define StaticAssert(test, errormsg)                         \
    do {} while (0)
#endif

#endif
/* vi:set tabstop=4 shiftwidth=4 expandtab: */
<|endoftext|>