<commit_before>/****************************************************************************
* Copyright (c) 2012, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Consulting LLC nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <memory>
#include <vector>

#include "NitfWriter.hpp"

#include <pdal/pdal_macros.hpp>

#include <pdal/PointView.hpp>
#include <pdal/GlobalEnvironment.hpp>

#ifdef PDAL_COMPILER_GCC
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Wredundant-decls"
#  pragma GCC diagnostic ignored "-Wextra"
#  pragma GCC diagnostic ignored "-Wcast-qual"
   // The following pragma doesn't actually work:
   //   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61653
#  pragma GCC diagnostic ignored "-Wliteral-suffix"
#endif
#include <ogr_spatialref.h>
#include <cpl_conv.h>
#ifdef PDAL_COMPILER_CLANG
#  pragma clang diagnostic push
#  pragma clang diagnostic ignored "-Wunused-private-field"
#endif

#define IMPORT_NITRO_API
#include <nitro/c++/import/nitf.hpp>
#include "tre_plugins.hpp"

#ifdef PDAL_COMPILER_CLANG
#  pragma clang diagnostic pop
#endif
#ifdef PDAL_COMPILER_GCC
#  pragma GCC diagnostic pop
#endif

// NOTES
//
// is it legal to write a LAZ file?
// syntactically, how do we name all the LAS writer options that we will pass to the las writer?
//

namespace pdal
{

static PluginInfo const s_info = PluginInfo(
    "writers.nitf",
    "NITF Writer",
    "http://pdal.io/stages/writers.nitf.html" );

CREATE_SHARED_PLUGIN(1, 0, NitfWriter, Writer, s_info)

std::string NitfWriter::getName() const { return s_info.name; }

BOX3D reprojectBoxToDD(const SpatialReference& reference, const BOX3D& box)
{
    if (reference.empty())
        return BOX3D();

    BOX3D output(box);

    OGRSpatialReferenceH current =
        OSRNewSpatialReference(reference.getWKT(SpatialReference::eCompoundOK, false).c_str());
    OGRSpatialReferenceH dd =
        OSRNewSpatialReference(0);

    OGRErr err = OSRSetFromUserInput(dd, const_cast<char *>("EPSG:4326"));
    if (err != OGRERR_NONE)
        throw std::invalid_argument("could not import coordinate system "
            "into OGRSpatialReference SetFromUserInput");

    OGRCoordinateTransformationH transform = OCTNewCoordinateTransformation(current, dd);

    int ret = OCTTransform(transform, 1, &output.minx, &output.miny, &output.minz);
    if (ret == 0)
    {
        std::ostringstream msg;
        msg << "Could not project point for reprojectBoxToDD::min" <<
            CPLGetLastErrorMsg() << ret;
        throw pdal_error(msg.str());
    }

    ret = OCTTransform(transform, 1, &output.maxx, &output.maxy, &output.maxz);
    if (ret == 0)
    {
        std::ostringstream msg;
        msg << "Could not project point for reprojectBoxToDD::max" <<
            CPLGetLastErrorMsg() << ret;
        throw pdal_error(msg.str());
    }

    OCTDestroyCoordinateTransformation(transform);
    OSRDestroySpatialReference(current);
    OSRDestroySpatialReference(dd);

    return output;
}

NitfWriter::NitfWriter() :  LasWriter(&m_oss)
{
    register_tre_plugins();
}

void NitfWriter::processOptions(const Options& options)
{
    LasWriter::processOptions(options);
    m_cLevel = options.getValueOrDefault<std::string>("CLEVEL","03");
    m_sType = options.getValueOrDefault<std::string>("STYPE","BF01");
    m_oStationId = options.getValueOrDefault<std::string>("OSTAID","PDAL");
    m_fileTitle = options.getValueOrDefault<std::string>("FTITLE",m_filename);
    m_fileClass = options.getValueOrDefault<std::string>("FSCLAS","U");
    m_origName = options.getValueOrDefault<std::string>("ONAME","");
    m_origPhone = options.getValueOrDefault<std::string>("OPHONE","");
    m_securityClass = options.getValueOrDefault<std::string>("FSCLAS","U");
    m_securityControlAndHandling = options.getValueOrDefault<std::string>("FSCTLH","");
    m_securityClassificationSystem = options.getValueOrDefault<std::string>("FSCLSY","");
    m_imgSecurityClass = options.getValueOrDefault<std::string>("FSCLAS","U");
    m_imgDate = getOptions().getValueOrDefault<std::string>("IDATIM", "");
    m_imgIdentifier2 = getOptions().getValueOrDefault<std::string>("IID2", "");
    m_sic = getOptions().getValueOrDefault<std::string>("FSCLTX", "");
    m_igeolob = getOptions().getValueOrDefault<std::string>("GEOLOB", "");
    try
    {
        m_aimidb = getOptions().getOption("AIMIDB");
    } catch (pdal::option_not_found&)
    {}
    try
    {
        m_acftb = getOptions().getOption("ACFTB");
    } catch (pdal::option_not_found&)
    {}
}

void NitfWriter::write(const PointViewPtr view)
{
    m_bounds.grow(view->calculateBounds(true));

    LasWriter::write(view);
}

void NitfWriter::done(PointTableRef table)
{
    LasWriter::done(table);

    try
    {
        ::nitf::Record record(NITF_VER_21);
        ::nitf::FileHeader header = record.getHeader();
        header.getFileHeader().set("NITF");
        header.getComplianceLevel().set(m_cLevel);
        header.getSystemType().set(m_sType);
        header.getOriginStationID().set(m_oStationId);
        header.getFileTitle().set(m_fileTitle);
        header.getClassification().set(m_fileClass);
        header.getMessageCopyNum().set("00000");
        header.getMessageNumCopies().set("00000");
        header.getEncrypted().set("0");
        header.getBackgroundColor().setRawData(const_cast<char*>("000"), 3);
        header.getOriginatorName().set(m_origName);
        header.getOriginatorPhone().set(m_origPhone);
        header.getSecurityGroup().getClassificationSystem().set(m_securityClassificationSystem);
        header.getSecurityGroup().getControlAndHandling().set(m_securityControlAndHandling);
        header.getSecurityGroup().getClassificationText().set(m_sic);

        ::nitf::DESegment des = record.newDataExtensionSegment();

        des.getSubheader().getFilePartType().set("DE");
        des.getSubheader().getTypeID().set("LIDARA DES");
        des.getSubheader().getVersion().set("01");
        des.getSubheader().getSecurityClass().set(m_securityClass);
        ::nitf::FileSecurity security = record.getHeader().getSecurityGroup();
        des.getSubheader().setSecurityGroup(security.clone());

        ::nitf::TRE usrHdr("LIDARA DES", "raw_data");
        usrHdr.setField("raw_data", "not");
        ::nitf::Field fld = usrHdr.getField("raw_data");
        fld.setType(::nitf::Field::BINARY);

        flush();
        m_oss.flush();
        std::streambuf *buf = m_oss.rdbuf();
        long size = buf->pubseekoff(0, m_oss.end);
        buf->pubseekoff(0, m_oss.beg);

        std::vector<char> bytes(size);
        buf->sgetn(bytes.data(), size);

        des.getSubheader().setSubheaderFields(usrHdr);

        ::nitf::ImageSegment image = record.newImageSegment();
        ::nitf::ImageSubheader subheader = image.getSubheader();

        BOX3D bounds =  reprojectBoxToDD(table.spatialRef(), m_bounds);

        //NITF decimal degree values for corner coordinates only has a precision of 3 after the decimal
        //This may cause an invalid polygon due to rounding errors with a small tile. Therefore instead of rounding
        //min values will use the floor value and max values will use the ceiling values.
        bounds.minx=(floor(bounds.minx*1000))/1000.0;
        bounds.miny=(floor(bounds.miny*1000))/1000.0;
        bounds.maxx=(ceil(bounds.maxx*1000))/1000.0;
        bounds.maxy=(ceil(bounds.maxy*1000))/1000.0;

        double corners[4][2];
        corners[0][0] = bounds.maxy;     corners[0][1] = bounds.minx;
        corners[1][0] = bounds.maxy;     corners[1][1] = bounds.maxx;
        corners[2][0] = bounds.miny;  corners[2][1] = bounds.maxx;
        corners[3][0] = bounds.miny;  corners[3][1] = bounds.minx;
        subheader.setCornersFromLatLons(NRT_CORNERS_DECIMAL, corners);

        subheader.getImageSecurityClass().set(m_imgSecurityClass);
        subheader.setSecurityGroup(security.clone());
        if (m_imgDate.size())
            subheader.getImageDateAndTime().set(m_imgDate);

        ::nitf::BandInfo info;
        ::nitf::LookupTable lt(0,0);
        info.init("G",    /* The band representation, Nth band */
                  " ",      /* The band subcategory */
                  "N",      /* The band filter condition */
                  "   ",    /* The band standard image filter code */
                  0,        /* The number of look-up tables */
                  0,        /* The number of entries/LUT */
                  lt);     /* The look-up tables */

        std::vector< ::nitf::BandInfo> bands;
        bands.push_back(info);
        subheader.setPixelInformation(
            "INT",      /* Pixel value type */
            8,         /* Number of bits/pixel */
            8,         /* Actual number of bits/pixel */
            "R",       /* Pixel justification */
            "NODISPLY",     /* Image representation */
            "VIS",     /* Image category */
            1,         /* Number of bands */
            bands);

        subheader.setBlocking(
            8,   /*!< The number of rows */
            8,  /*!< The number of columns */
            8, /*!< The number of rows/block */
            8,  /*!< The number of columns/block */
            "P");                /*!< Image mode */

        //Image Header fields to set
        subheader.getImageId().set("None");
        subheader.getImageTitle().set(m_imgIdentifier2);

        // 64 char string
        std::string zeros(64, '0');

        std::unique_ptr< ::nitf::BandSource> band(new ::nitf::MemorySource(
            const_cast<char*>(zeros.c_str()),
            zeros.size() /* memory size */,
            0 /* starting offset */,
            1 /* bytes per pixel */,
            0 /*skip*/));
        ::nitf::ImageSource iSource;
        iSource.addBand(*band);

        //AIMIDB
        if (!m_aimidb.empty())
        {
            boost::optional<const Options&> options = m_aimidb.getOptions();
            if (options)
            {
                ::nitf::TRE tre("AIMIDB");
                std::vector<Option> opts = options->getOptions();
                for (auto i = opts.begin(); i != opts.end(); ++i)
                {
                    tre.setField(i->getName(), i->getValue<std::string>());
                }
                subheader.getExtendedSection().appendTRE(tre);
            }
        }

        //ACFTB
        if (!m_acftb.empty())
        {
            boost::optional<const Options&> options = m_acftb.getOptions();
            if (options)
            {
                ::nitf::TRE tre("ACFTB");
                std::vector<Option> opts = options->getOptions();
                for (auto i = opts.begin(); i != opts.end(); ++i)
                {
                    tre.setField(i->getName(), i->getValue<std::string>());
                }
                subheader.getExtendedSection().appendTRE(tre);
            }
        }

        ::nitf::Writer writer;
        ::nitf::IOHandle output_io(m_filename.c_str(), NITF_ACCESS_WRITEONLY,
            NITF_CREATE);
        writer.prepare(output_io, record);

        ::nitf::SegmentWriter sWriter = writer.newDEWriter(0);

        ::nitf::SegmentMemorySource sSource(bytes.data(), size, 0, 0, false);
        sWriter.attachSource(sSource);

        ::nitf::ImageWriter iWriter = writer.newImageWriter(0);
        iWriter.attachSource(iSource);

        writer.write();
        output_io.close();
    }
    catch (except::Throwable & t)
    {
        std::ostringstream oss;
        // std::cout << t.getTrace();
        throw pdal_error(t.getMessage());
    }
}

} // namespaces
<commit_msg>Formatting.<commit_after>/****************************************************************************
* Copyright (c) 2012, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Consulting LLC nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <memory>
#include <vector>

#include "NitfWriter.hpp"

#include <pdal/pdal_macros.hpp>

#include <pdal/PointView.hpp>
#include <pdal/GlobalEnvironment.hpp>

#ifdef PDAL_COMPILER_GCC
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Wredundant-decls"
#  pragma GCC diagnostic ignored "-Wextra"
#  pragma GCC diagnostic ignored "-Wcast-qual"
   // The following pragma doesn't actually work:
   //   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61653
#  pragma GCC diagnostic ignored "-Wliteral-suffix"
#endif
#include <ogr_spatialref.h>
#include <cpl_conv.h>
#ifdef PDAL_COMPILER_CLANG
#  pragma clang diagnostic push
#  pragma clang diagnostic ignored "-Wunused-private-field"
#endif

#define IMPORT_NITRO_API
#include <nitro/c++/import/nitf.hpp>
#include "tre_plugins.hpp"

#ifdef PDAL_COMPILER_CLANG
#  pragma clang diagnostic pop
#endif
#ifdef PDAL_COMPILER_GCC
#  pragma GCC diagnostic pop
#endif

// NOTES
//
// is it legal to write a LAZ file?
// syntactically, how do we name all the LAS writer options that we will pass to the las writer?
//

namespace pdal
{

static PluginInfo const s_info = PluginInfo(
    "writers.nitf",
    "NITF Writer",
    "http://pdal.io/stages/writers.nitf.html" );

CREATE_SHARED_PLUGIN(1, 0, NitfWriter, Writer, s_info)

std::string NitfWriter::getName() const { return s_info.name; }

BOX3D reprojectBoxToDD(const SpatialReference& reference, const BOX3D& box)
{
    if (reference.empty())
        return BOX3D();

    BOX3D output(box);

    OGRSpatialReferenceH current =
        OSRNewSpatialReference(reference.getWKT(SpatialReference::eCompoundOK, false).c_str());
    OGRSpatialReferenceH dd =
        OSRNewSpatialReference(0);

    OGRErr err = OSRSetFromUserInput(dd, const_cast<char *>("EPSG:4326"));
    if (err != OGRERR_NONE)
        throw std::invalid_argument("could not import coordinate system "
            "into OGRSpatialReference SetFromUserInput");

    OGRCoordinateTransformationH transform = OCTNewCoordinateTransformation(current, dd);

    int ret = OCTTransform(transform, 1, &output.minx, &output.miny, &output.minz);
    if (ret == 0)
    {
        std::ostringstream msg;
        msg << "Could not project point for reprojectBoxToDD::min" <<
            CPLGetLastErrorMsg() << ret;
        throw pdal_error(msg.str());
    }

    ret = OCTTransform(transform, 1, &output.maxx, &output.maxy, &output.maxz);
    if (ret == 0)
    {
        std::ostringstream msg;
        msg << "Could not project point for reprojectBoxToDD::max" <<
            CPLGetLastErrorMsg() << ret;
        throw pdal_error(msg.str());
    }

    OCTDestroyCoordinateTransformation(transform);
    OSRDestroySpatialReference(current);
    OSRDestroySpatialReference(dd);

    return output;
}

NitfWriter::NitfWriter() :  LasWriter(&m_oss)
{
    register_tre_plugins();
}

void NitfWriter::processOptions(const Options& options)
{
    LasWriter::processOptions(options);
    m_cLevel = options.getValueOrDefault<std::string>("CLEVEL","03");
    m_sType = options.getValueOrDefault<std::string>("STYPE","BF01");
    m_oStationId = options.getValueOrDefault<std::string>("OSTAID","PDAL");
    m_fileTitle = options.getValueOrDefault<std::string>("FTITLE",m_filename);
    m_fileClass = options.getValueOrDefault<std::string>("FSCLAS","U");
    m_origName = options.getValueOrDefault<std::string>("ONAME","");
    m_origPhone = options.getValueOrDefault<std::string>("OPHONE","");
    m_securityClass = options.getValueOrDefault<std::string>("FSCLAS","U");
    m_securityControlAndHandling = options.getValueOrDefault<std::string>("FSCTLH","");
    m_securityClassificationSystem = options.getValueOrDefault<std::string>("FSCLSY","");
    m_imgSecurityClass = options.getValueOrDefault<std::string>("FSCLAS","U");
    m_imgDate = getOptions().getValueOrDefault<std::string>("IDATIM", "");
    m_imgIdentifier2 = getOptions().getValueOrDefault<std::string>("IID2", "");
    m_sic = getOptions().getValueOrDefault<std::string>("FSCLTX", "");
    m_igeolob = getOptions().getValueOrDefault<std::string>("GEOLOB", "");
    try
    {
        m_aimidb = getOptions().getOption("AIMIDB");
    } catch (pdal::option_not_found&)
    {}
    try
    {
        m_acftb = getOptions().getOption("ACFTB");
    } catch (pdal::option_not_found&)
    {}
}

void NitfWriter::write(const PointViewPtr view)
{
    m_bounds.grow(view->calculateBounds(true));

    LasWriter::write(view);
}

void NitfWriter::done(PointTableRef table)
{
    LasWriter::done(table);

    try
    {
        ::nitf::Record record(NITF_VER_21);
        ::nitf::FileHeader header = record.getHeader();
        header.getFileHeader().set("NITF");
        header.getComplianceLevel().set(m_cLevel);
        header.getSystemType().set(m_sType);
        header.getOriginStationID().set(m_oStationId);
        header.getFileTitle().set(m_fileTitle);
        header.getClassification().set(m_fileClass);
        header.getMessageCopyNum().set("00000");
        header.getMessageNumCopies().set("00000");
        header.getEncrypted().set("0");
        header.getBackgroundColor().setRawData(const_cast<char*>("000"), 3);
        header.getOriginatorName().set(m_origName);
        header.getOriginatorPhone().set(m_origPhone);
        header.getSecurityGroup().getClassificationSystem().set(m_securityClassificationSystem);
        header.getSecurityGroup().getControlAndHandling().set(m_securityControlAndHandling);
        header.getSecurityGroup().getClassificationText().set(m_sic);

        ::nitf::DESegment des = record.newDataExtensionSegment();

        des.getSubheader().getFilePartType().set("DE");
        des.getSubheader().getTypeID().set("LIDARA DES");
        des.getSubheader().getVersion().set("01");
        des.getSubheader().getSecurityClass().set(m_securityClass);
        ::nitf::FileSecurity security = record.getHeader().getSecurityGroup();
        des.getSubheader().setSecurityGroup(security.clone());

        ::nitf::TRE usrHdr("LIDARA DES", "raw_data");
        usrHdr.setField("raw_data", "not");
        ::nitf::Field fld = usrHdr.getField("raw_data");
        fld.setType(::nitf::Field::BINARY);

        flush();
        m_oss.flush();
        std::streambuf *buf = m_oss.rdbuf();
        long size = buf->pubseekoff(0, m_oss.end);
        buf->pubseekoff(0, m_oss.beg);

        std::vector<char> bytes(size);
        buf->sgetn(bytes.data(), size);

        des.getSubheader().setSubheaderFields(usrHdr);

        ::nitf::ImageSegment image = record.newImageSegment();
        ::nitf::ImageSubheader subheader = image.getSubheader();

        BOX3D bounds =  reprojectBoxToDD(table.spatialRef(), m_bounds);

        //NITF decimal degree values for corner coordinates only has a
        // precision of 3 after the decimal. This may cause an invalid
        // polygon due to rounding errors with a small tile. Therefore
        // instead of rounding min values will use the floor value and
        // max values will use the ceiling values.
        bounds.minx = (floor(bounds.minx * 1000)) / 1000.0;
        bounds.miny = (floor(bounds.miny * 1000)) / 1000.0;
        bounds.maxx = (ceil(bounds.maxx * 1000)) / 1000.0;
        bounds.maxy = (ceil(bounds.maxy * 1000)) / 1000.0;

        double corners[4][2];
        corners[0][0] = bounds.maxy;
        corners[0][1] = bounds.minx;
        corners[1][0] = bounds.maxy;
        corners[1][1] = bounds.maxx;
        corners[2][0] = bounds.miny;
        corners[2][1] = bounds.maxx;
        corners[3][0] = bounds.miny;
        corners[3][1] = bounds.minx;
        subheader.setCornersFromLatLons(NRT_CORNERS_DECIMAL, corners);

        subheader.getImageSecurityClass().set(m_imgSecurityClass);
        subheader.setSecurityGroup(security.clone());
        if (m_imgDate.size())
            subheader.getImageDateAndTime().set(m_imgDate);

        ::nitf::BandInfo info;
        ::nitf::LookupTable lt(0,0);
        info.init("G",    /* The band representation, Nth band */
                  " ",      /* The band subcategory */
                  "N",      /* The band filter condition */
                  "   ",    /* The band standard image filter code */
                  0,        /* The number of look-up tables */
                  0,        /* The number of entries/LUT */
                  lt);     /* The look-up tables */

        std::vector< ::nitf::BandInfo> bands;
        bands.push_back(info);
        subheader.setPixelInformation(
            "INT",      /* Pixel value type */
            8,         /* Number of bits/pixel */
            8,         /* Actual number of bits/pixel */
            "R",       /* Pixel justification */
            "NODISPLY",     /* Image representation */
            "VIS",     /* Image category */
            1,         /* Number of bands */
            bands);

        subheader.setBlocking(
            8,   /*!< The number of rows */
            8,  /*!< The number of columns */
            8, /*!< The number of rows/block */
            8,  /*!< The number of columns/block */
            "P");                /*!< Image mode */

        //Image Header fields to set
        subheader.getImageId().set("None");
        subheader.getImageTitle().set(m_imgIdentifier2);

        // 64 char string
        std::string zeros(64, '0');

        std::unique_ptr< ::nitf::BandSource> band(new ::nitf::MemorySource(
            const_cast<char*>(zeros.c_str()),
            zeros.size() /* memory size */,
            0 /* starting offset */,
            1 /* bytes per pixel */,
            0 /*skip*/));
        ::nitf::ImageSource iSource;
        iSource.addBand(*band);

        //AIMIDB
        if (!m_aimidb.empty())
        {
            boost::optional<const Options&> options = m_aimidb.getOptions();
            if (options)
            {
                ::nitf::TRE tre("AIMIDB");
                std::vector<Option> opts = options->getOptions();
                for (auto i = opts.begin(); i != opts.end(); ++i)
                {
                    tre.setField(i->getName(), i->getValue<std::string>());
                }
                subheader.getExtendedSection().appendTRE(tre);
            }
        }

        //ACFTB
        if (!m_acftb.empty())
        {
            boost::optional<const Options&> options = m_acftb.getOptions();
            if (options)
            {
                ::nitf::TRE tre("ACFTB");
                std::vector<Option> opts = options->getOptions();
                for (auto i = opts.begin(); i != opts.end(); ++i)
                {
                    tre.setField(i->getName(), i->getValue<std::string>());
                }
                subheader.getExtendedSection().appendTRE(tre);
            }
        }

        ::nitf::Writer writer;
        ::nitf::IOHandle output_io(m_filename.c_str(), NITF_ACCESS_WRITEONLY,
            NITF_CREATE);
        writer.prepare(output_io, record);

        ::nitf::SegmentWriter sWriter = writer.newDEWriter(0);

        ::nitf::SegmentMemorySource sSource(bytes.data(), size, 0, 0, false);
        sWriter.attachSource(sSource);

        ::nitf::ImageWriter iWriter = writer.newImageWriter(0);
        iWriter.attachSource(iSource);

        writer.write();
        output_io.close();
    }
    catch (except::Throwable & t)
    {
        std::ostringstream oss;
        // std::cout << t.getTrace();
        throw pdal_error(t.getMessage());
    }
}

} // namespaces
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2020 Trevor Pounds <trevor.pounds@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "tpunit++.hpp"

/**
 * Test tpunit++ internal logic, macros and compiler support.
 */
struct TPUnitPPTest : tpunit::TestFixture {
   TPUnitPPTest() {
      BEFORE_CLASS(TPUnitPPTest::before_class);
      BEFORE(TPUnitPPTest::before);
      TEST(TPUnitPPTest::test); TEST(TPUnitPPTest::test);
      TEST(TPUnitPPTest::test); TEST(TPUnitPPTest::test);
      TEST(TPUnitPPTest::test); TEST(TPUnitPPTest::test);
      TEST(TPUnitPPTest::test); TEST(TPUnitPPTest::test);
      TEST(TPUnitPPTest::test_invocations);
      TEST(TPUnitPPTest::test_exceptions);
      TEST(TPUnitPPTest::test_macros);
      TEST(TPUnitPPTest::test_matchers);
      AFTER(TPUnitPPTest::after);
      AFTER_CLASS(TPUnitPPTest::after_class);
   }

   int __after_num,  __after_class_num,
       __before_num, __before_class_num,
       __test_num;

   void after()        { __after_num++; }
   void after_class()  { __after_class_num++; }
   void before()       { __before_num++; }
   void before_class() { __before_class_num++; }
   void test()         { __test_num++; }

   void test_invocations() {
      ASSERT_EQUAL(__after_num,        8);
      ASSERT_EQUAL(__after_class_num,  0);
      ASSERT_EQUAL(__before_num,       9);
      ASSERT_EQUAL(__before_class_num, 1);
      ASSERT_EQUAL(__test_num,         8);
   }

   void test_macros() {
      PASS();
      ASSERT_TRUE(true);               EXPECT_TRUE(true);
      ASSERT_FALSE(false);             EXPECT_FALSE(false);
      ASSERT_EQUAL(0, 0);              EXPECT_EQUAL(0, 0);
      ASSERT_NOT_EQUAL(true, false);   EXPECT_NOT_EQUAL(true, false);
      ASSERT_GREATER_THAN(1, 0);       EXPECT_GREATER_THAN(1, 0);
      ASSERT_GREATER_THAN_EQUAL(1, 0); EXPECT_GREATER_THAN_EQUAL(1, 0);
      ASSERT_GREATER_THAN_EQUAL(1, 1); EXPECT_GREATER_THAN_EQUAL(1, 1);
      ASSERT_LESS_THAN(0, 1);          EXPECT_LESS_THAN(0, 1);
      ASSERT_LESS_THAN_EQUAL(0, 1);    EXPECT_LESS_THAN_EQUAL(0, 1);
      ASSERT_LESS_THAN_EQUAL(1, 1);    EXPECT_LESS_THAN_EQUAL(1, 1);
      ASSERT_FLOAT_EQUAL(3.14159265f, 3.141592650000001f); EXPECT_FLOAT_EQUAL(3.14159265f, 3.141592650001f);
      ASSERT_FLOAT_EQUAL(0.0f,        -0.0f);              EXPECT_FLOAT_EQUAL(0.0f,        -0.0f);
      ASSERT_FLOAT_EQUAL(1.77245385,  1.7724538500000001); EXPECT_FLOAT_EQUAL(1.77245385,  1.7724538500000001);
      ASSERT_FLOAT_EQUAL(0.0,         -0.0);               EXPECT_FLOAT_EQUAL(0.0,         -0.0);
      ASSERT_FLOAT_NEAR(3.14159265f,  3.1400001f, 0.002f); EXPECT_FLOAT_NEAR(3.14159265f,  3.1400001f, 0.002f);
      ASSERT_FLOAT_NEAR(1.77245385,   1.77240000, 0.0005); EXPECT_FLOAT_NEAR(1.77245385,   1.77240000, 0.0005);
   }

   void test_exceptions() {
#if defined(TPUNITPP_HAS_EXCEPTIONS)
         int __dummy = 0;
         ASSERT_THROW(throw __dummy, int); EXPECT_THROW(throw __dummy, int);
         ASSERT_NO_THROW(__dummy = 1);     EXPECT_NO_THROW(__dummy = 1);
         ASSERT_ANY_THROW(throw __dummy);  EXPECT_ANY_THROW(throw __dummy);
#else
         TRACE("TEST IGNORED! TPUNITPP_HAS_EXCEPTIONS = 0");
#endif
   }

   struct AlwaysMatches {
      template <typename T>
      bool matches(T) { return true; }
   };

   struct NeverMatches {
      template <typename T>
      bool matches(T) { return false; }
   };

   void test_matchers() {
      ASSERT_THAT(true, AlwaysMatches());
      EXPECT_THAT(1234, AlwaysMatches());

      ASSERT_THAT("TEST", !NeverMatches());
      EXPECT_THAT(3.141f, !NeverMatches());
   }
} __TPUnitPPTest;
<commit_msg>Cleanup duplicate test calls.<commit_after>/**
 * Copyright (c) 2011-2020 Trevor Pounds <trevor.pounds@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "tpunit++.hpp"

/**
 * Test tpunit++ internal logic, macros and compiler support.
 */
struct TPUnitPPTest : tpunit::TestFixture {
   TPUnitPPTest() {
      BEFORE_CLASS(TPUnitPPTest::before_class);
      BEFORE(TPUnitPPTest::before);
      TEST(TPUnitPPTest::test);
      TEST(TPUnitPPTest::test_exceptions);
      TEST(TPUnitPPTest::test_macros);
      TEST(TPUnitPPTest::test_matchers);
      TEST(TPUnitPPTest::test_stats);
      AFTER(TPUnitPPTest::after);
      AFTER_CLASS(TPUnitPPTest::after_class);
   }

   int __after_num,  __after_class_num,
       __before_num, __before_class_num,
       __test_num;

   void after()        { __after_num++; }
   void after_class()  { __after_class_num++; }
   void before()       { __before_num++; }
   void before_class() { __before_class_num++; }
   void test()         { __test_num++; }

   void test_stats() {
      ASSERT_EQUAL(__after_num,        4);
      ASSERT_EQUAL(__after_class_num,  0);
      ASSERT_EQUAL(__before_num,       5);
      ASSERT_EQUAL(__before_class_num, 1);
      ASSERT_EQUAL(__test_num,         1);
   }

   void test_macros() {
      PASS();
      ASSERT_TRUE(true);               EXPECT_TRUE(true);
      ASSERT_FALSE(false);             EXPECT_FALSE(false);
      ASSERT_EQUAL(0, 0);              EXPECT_EQUAL(0, 0);
      ASSERT_NOT_EQUAL(true, false);   EXPECT_NOT_EQUAL(true, false);
      ASSERT_GREATER_THAN(1, 0);       EXPECT_GREATER_THAN(1, 0);
      ASSERT_GREATER_THAN_EQUAL(1, 0); EXPECT_GREATER_THAN_EQUAL(1, 0);
      ASSERT_GREATER_THAN_EQUAL(1, 1); EXPECT_GREATER_THAN_EQUAL(1, 1);
      ASSERT_LESS_THAN(0, 1);          EXPECT_LESS_THAN(0, 1);
      ASSERT_LESS_THAN_EQUAL(0, 1);    EXPECT_LESS_THAN_EQUAL(0, 1);
      ASSERT_LESS_THAN_EQUAL(1, 1);    EXPECT_LESS_THAN_EQUAL(1, 1);
      ASSERT_FLOAT_EQUAL(3.14159265f, 3.141592650000001f); EXPECT_FLOAT_EQUAL(3.14159265f, 3.141592650001f);
      ASSERT_FLOAT_EQUAL(0.0f,        -0.0f);              EXPECT_FLOAT_EQUAL(0.0f,        -0.0f);
      ASSERT_FLOAT_EQUAL(1.77245385,  1.7724538500000001); EXPECT_FLOAT_EQUAL(1.77245385,  1.7724538500000001);
      ASSERT_FLOAT_EQUAL(0.0,         -0.0);               EXPECT_FLOAT_EQUAL(0.0,         -0.0);
      ASSERT_FLOAT_NEAR(3.14159265f,  3.1400001f, 0.002f); EXPECT_FLOAT_NEAR(3.14159265f,  3.1400001f, 0.002f);
      ASSERT_FLOAT_NEAR(1.77245385,   1.77240000, 0.0005); EXPECT_FLOAT_NEAR(1.77245385,   1.77240000, 0.0005);
   }

   void test_exceptions() {
#if defined(TPUNITPP_HAS_EXCEPTIONS)
         int __dummy = 0;
         ASSERT_THROW(throw __dummy, int); EXPECT_THROW(throw __dummy, int);
         ASSERT_NO_THROW(__dummy = 1);     EXPECT_NO_THROW(__dummy = 1);
         ASSERT_ANY_THROW(throw __dummy);  EXPECT_ANY_THROW(throw __dummy);
#else
         TRACE("TEST IGNORED! TPUNITPP_HAS_EXCEPTIONS = 0");
#endif
   }

   struct AlwaysMatches {
      template <typename T>
      bool matches(T) { return true; }
   };

   struct NeverMatches {
      template <typename T>
      bool matches(T) { return false; }
   };

   void test_matchers() {
      ASSERT_THAT(true, AlwaysMatches());
      EXPECT_THAT(1234, AlwaysMatches());

      ASSERT_THAT("TEST", !NeverMatches());
      EXPECT_THAT(3.141f, !NeverMatches());
   }
} __TPUnitPPTest;
<|endoftext|>


<commit_before>#ifndef UTILS_HPP
#define UTILS_HPP

#include <glm/glm.hpp>

#include <SDL.h>
#include <SDL_ttf.h>

#include <cmath>
#include <string>
#include <iostream>

namespace trac0r {

SDL_Texture *make_text(SDL_Renderer *renderer, TTF_Font *font, std::string text,
                       const SDL_Color &color) {
    auto text_surface = TTF_RenderText_Blended(font, text.c_str(), color);
    auto text_tex = SDL_CreateTextureFromSurface(renderer, text_surface);
    SDL_FreeSurface(text_surface);

    return text_tex;
}

void render_text(SDL_Renderer *renderer, SDL_Texture *texture, int pos_x, int pos_y) {
    int tex_width;
    int tex_height;

    SDL_QueryTexture(texture, 0, 0, &tex_width, &tex_height);
    SDL_Rect rect{pos_x, pos_y, tex_width, tex_height};
    SDL_RenderCopy(renderer, texture, 0, &rect);
}

// Möller-Trumbore intersection algorithm
// (see https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm)
bool intersect_ray_triangle(const glm::vec3 &origin, const glm::vec3 &dir, const glm::vec3 &v0, glm::vec3 &v1, glm::vec3 &v2, float &dist) {
    // Calculate edges of triangle from v0.
    auto e0 = v1 - v0;
    auto e1 = v2 - v0;

    // Calculate determinant to check whether the ray is in the newly calculated plane made up from e0 and e1.
    auto pvec = glm::cross(dir, e1);
    auto det = glm::dot(e0, pvec);

    // Check whether determinant is close to 0. If that is the case, the ray is in the same plane as the triangle itself which means that they can't collide. This effectively disables backface culling for which we would instead only check whether det < epsilon.
    auto epsilon = std::numeric_limits<float>::epsilon();
    if (det > -epsilon && det < epsilon)
        return false;

    auto inv_det = 1.f / det;

    // Calculate distance from v0 to ray origin
    auto tdist = origin - v0;

    // Calculate u parameter and test bound
    auto u = glm::dot(tdist, pvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (u < 0.f || u > 1.f)
        return false;

    // Prepare to test v parameter
    auto qvec = glm::cross(tdist, e0);

    // Calculate v parameter and test bound
    auto v = glm::dot(dir, qvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (v < 0.f || v > 1.f)
        return false;

    auto t = glm::dot(e1, qvec) * inv_det;

    if (t > epsilon) {
        dist = t;
        return true;
    }

    // If we end up here, there was no hit
    return false;
}

uint32_t pack_color_argb(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
    uint32_t new_color = a << 24 | r << 16 | g << 8 | b;
    return new_color;
}

uint32_t pack_color_argb(glm::i8vec4 color) {
    uint32_t new_color = color.a << 24 | color.r << 16 | color.g << 8 | color.b;
    return new_color;
}

uint32_t pack_color_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    uint32_t packed_color = r << 24 | g << 16 | b << 8 | a;
    return packed_color;
}

uint32_t pack_color_rgba(glm::i8vec4 color) {
    uint32_t packed_color = color.r << 24 | color.g << 16 | color.b << 8 | color.a;
    return packed_color;
}

uint32_t pack_color_rgba(glm::vec4 color) {
    uint32_t packed_color = int(std::round(color.r * 255)) << 24 |
                            int(std::round(color.g * 255)) << 16 |
                            int(std::round(color.b * 255)) << 8 | int(std::round(color.a * 255));
    return packed_color;
}

uint32_t pack_color_argb(glm::vec4 color) {
    uint32_t packed_color = int(std::round(color.a * 255)) << 24 |
                            int(std::round(color.r * 255)) << 16 |
                            int(std::round(color.g * 255)) << 8 | int(std::round(color.b * 255));
    return packed_color;
}

glm::i8vec4 unpack_color_rgba_to_i8vec4(uint32_t packed_color_rgba) {
    glm::i8vec4 unpacked_color;
    unpacked_color.r = packed_color_rgba >> 24 & 0xFF;
    unpacked_color.g = packed_color_rgba >> 16 & 0xFF;
    unpacked_color.b = packed_color_rgba >> 8 & 0xFF;
    unpacked_color.a = packed_color_rgba & 0xFF;
    return unpacked_color;
}

glm::i8vec4 unpack_color_argb_to_i8vec4(uint32_t packed_color_argb) {
    glm::i8vec4 unpacked_color;
    unpacked_color.a = packed_color_argb >> 24 & 0xFF;
    unpacked_color.r = packed_color_argb >> 16 & 0xFF;
    unpacked_color.g = packed_color_argb >> 8 & 0xFF;
    unpacked_color.b = packed_color_argb & 0xFF;
    return unpacked_color;
}

glm::vec4 unpack_color_rgbb_to_vec4(uint32_t packed_color_rgba) {
    glm::i8vec4 unpacked_color;
    unpacked_color.r = (packed_color_rgba >> 24 & 0xFF) / 255.f;
    unpacked_color.g = (packed_color_rgba >> 16 & 0xFF) / 255.f;
    unpacked_color.b = (packed_color_rgba >> 8 & 0xFF) / 255.f;
    unpacked_color.a = (packed_color_rgba & 0xFF) / 255.f;
    return unpacked_color;
}

glm::vec4 unpack_color_argb_to_vec4(uint32_t packed_color_argb) {
    glm::vec4 unpacked_color;
    unpacked_color.a = (packed_color_argb >> 24 & 0xFF) / 255.f;
    unpacked_color.r = (packed_color_argb >> 16 & 0xFF) / 255.f;
    unpacked_color.g = (packed_color_argb >> 8 & 0xFF) / 255.f;
    unpacked_color.b = (packed_color_argb & 0xFF) / 255.f;
    return unpacked_color;
}
}

#endif /* end of include guard: UTILS_HPP */
<commit_msg>Rename tdist to tvec for clarity<commit_after>#ifndef UTILS_HPP
#define UTILS_HPP

#include <glm/glm.hpp>

#include <SDL.h>
#include <SDL_ttf.h>

#include <cmath>
#include <string>
#include <iostream>

namespace trac0r {

SDL_Texture *make_text(SDL_Renderer *renderer, TTF_Font *font, std::string text,
                       const SDL_Color &color) {
    auto text_surface = TTF_RenderText_Blended(font, text.c_str(), color);
    auto text_tex = SDL_CreateTextureFromSurface(renderer, text_surface);
    SDL_FreeSurface(text_surface);

    return text_tex;
}

void render_text(SDL_Renderer *renderer, SDL_Texture *texture, int pos_x, int pos_y) {
    int tex_width;
    int tex_height;

    SDL_QueryTexture(texture, 0, 0, &tex_width, &tex_height);
    SDL_Rect rect{pos_x, pos_y, tex_width, tex_height};
    SDL_RenderCopy(renderer, texture, 0, &rect);
}

// Möller-Trumbore intersection algorithm
// (see https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm)
bool intersect_ray_triangle(const glm::vec3 &origin, const glm::vec3 &dir, const glm::vec3 &v0, glm::vec3 &v1, glm::vec3 &v2, float &dist) {
    // Calculate edges of triangle from v0.
    auto e0 = v1 - v0;
    auto e1 = v2 - v0;

    // Calculate determinant to check whether the ray is in the newly calculated plane made up from e0 and e1.
    auto pvec = glm::cross(dir, e1);
    auto det = glm::dot(e0, pvec);

    // Check whether determinant is close to 0. If that is the case, the ray is in the same plane as the triangle itself which means that they can't collide. This effectively disables backface culling for which we would instead only check whether det < epsilon.
    auto epsilon = std::numeric_limits<float>::epsilon();
    if (det > -epsilon && det < epsilon)
        return false;

    auto inv_det = 1.f / det;

    // Calculate distance from v0 to ray origin
    auto tvec = origin - v0;

    // Calculate u parameter and test bound
    auto u = glm::dot(tvec, pvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (u < 0.f || u > 1.f)
        return false;

    // Prepare to test v parameter
    auto qvec = glm::cross(tvec, e0);

    // Calculate v parameter and test bound
    auto v = glm::dot(dir, qvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (v < 0.f || v > 1.f)
        return false;

    auto t = glm::dot(e1, qvec) * inv_det;

    if (t > epsilon) {
        dist = t;
        return true;
    }

    // If we end up here, there was no hit
    return false;
}

uint32_t pack_color_argb(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
    uint32_t new_color = a << 24 | r << 16 | g << 8 | b;
    return new_color;
}

uint32_t pack_color_argb(glm::i8vec4 color) {
    uint32_t new_color = color.a << 24 | color.r << 16 | color.g << 8 | color.b;
    return new_color;
}

uint32_t pack_color_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    uint32_t packed_color = r << 24 | g << 16 | b << 8 | a;
    return packed_color;
}

uint32_t pack_color_rgba(glm::i8vec4 color) {
    uint32_t packed_color = color.r << 24 | color.g << 16 | color.b << 8 | color.a;
    return packed_color;
}

uint32_t pack_color_rgba(glm::vec4 color) {
    uint32_t packed_color = int(std::round(color.r * 255)) << 24 |
                            int(std::round(color.g * 255)) << 16 |
                            int(std::round(color.b * 255)) << 8 | int(std::round(color.a * 255));
    return packed_color;
}

uint32_t pack_color_argb(glm::vec4 color) {
    uint32_t packed_color = int(std::round(color.a * 255)) << 24 |
                            int(std::round(color.r * 255)) << 16 |
                            int(std::round(color.g * 255)) << 8 | int(std::round(color.b * 255));
    return packed_color;
}

glm::i8vec4 unpack_color_rgba_to_i8vec4(uint32_t packed_color_rgba) {
    glm::i8vec4 unpacked_color;
    unpacked_color.r = packed_color_rgba >> 24 & 0xFF;
    unpacked_color.g = packed_color_rgba >> 16 & 0xFF;
    unpacked_color.b = packed_color_rgba >> 8 & 0xFF;
    unpacked_color.a = packed_color_rgba & 0xFF;
    return unpacked_color;
}

glm::i8vec4 unpack_color_argb_to_i8vec4(uint32_t packed_color_argb) {
    glm::i8vec4 unpacked_color;
    unpacked_color.a = packed_color_argb >> 24 & 0xFF;
    unpacked_color.r = packed_color_argb >> 16 & 0xFF;
    unpacked_color.g = packed_color_argb >> 8 & 0xFF;
    unpacked_color.b = packed_color_argb & 0xFF;
    return unpacked_color;
}

glm::vec4 unpack_color_rgbb_to_vec4(uint32_t packed_color_rgba) {
    glm::i8vec4 unpacked_color;
    unpacked_color.r = (packed_color_rgba >> 24 & 0xFF) / 255.f;
    unpacked_color.g = (packed_color_rgba >> 16 & 0xFF) / 255.f;
    unpacked_color.b = (packed_color_rgba >> 8 & 0xFF) / 255.f;
    unpacked_color.a = (packed_color_rgba & 0xFF) / 255.f;
    return unpacked_color;
}

glm::vec4 unpack_color_argb_to_vec4(uint32_t packed_color_argb) {
    glm::vec4 unpacked_color;
    unpacked_color.a = (packed_color_argb >> 24 & 0xFF) / 255.f;
    unpacked_color.r = (packed_color_argb >> 16 & 0xFF) / 255.f;
    unpacked_color.g = (packed_color_argb >> 8 & 0xFF) / 255.f;
    unpacked_color.b = (packed_color_argb & 0xFF) / 255.f;
    return unpacked_color;
}
}

#endif /* end of include guard: UTILS_HPP */
<|endoftext|>


<commit_before>// Scintilla source code edit control
// KeyMap.cxx  - defines a mapping between keystrokes and commands
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include "Platform.h"

#include "Scintilla.h"

#include "KeyMap.h"

KeyMap::KeyMap() : kmap(0), len(0), alloc(0) {
	for (int i = 0; MapDefault[i].key; i++) {
		AssignCmdKey(MapDefault[i].key,
			MapDefault[i].modifiers,
             		MapDefault[i].msg);
	}
}

KeyMap::~KeyMap() {
	Clear();
}

void KeyMap::Clear() {
	delete []kmap;
	kmap = 0;
	len = 0;
	alloc = 0;
}

void KeyMap::AssignCmdKey(int key, int modifiers, UINT msg) {
	if ((len+1) >= alloc) {
		KeyToCommand *ktcNew = new KeyToCommand[alloc + 5];
		if (!ktcNew)
			return;
		for (int k=0;k<len;k++)
			ktcNew[k] = kmap[k];
		alloc += 5;
		delete []kmap;
		kmap = ktcNew;
	}
	for (int keyIndex = 0; keyIndex < len; keyIndex++) {
		if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) {
			kmap[keyIndex].msg = msg;
			return;
		}
	}
	kmap[len].key = key;
	kmap[len].modifiers = modifiers;
	kmap[len].msg = msg;
	len++;
}

UINT KeyMap::Find(int key, int modifiers) {
	for (int i=0; i < len; i++) {
		if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) {
			return kmap[i].msg;
		}
	}
	return 0;
}

KeyToCommand KeyMap::MapDefault[] = {
    {VK_DOWN,		SCI_NORM,	SCI_LINEDOWN},
    {VK_DOWN,		SCI_SHIFT,	SCI_LINEDOWNEXTEND},
    {VK_DOWN,		SCI_CTRL,	SCI_LINESCROLLDOWN},
    {VK_UP,			SCI_NORM,	SCI_LINEUP},
    {VK_UP,			SCI_SHIFT,	SCI_LINEUPEXTEND},
    {VK_UP,			SCI_CTRL,	SCI_LINESCROLLUP},
    {VK_LEFT,		SCI_NORM,	SCI_CHARLEFT},
    {VK_LEFT,		SCI_SHIFT,	SCI_CHARLEFTEXTEND},
    {VK_LEFT,		SCI_CTRL,	SCI_WORDLEFT},
    {VK_LEFT,		SCI_CSHIFT,	SCI_WORDLEFTEXTEND},
    {VK_RIGHT,		SCI_NORM,	SCI_CHARRIGHT},
    {VK_RIGHT,		SCI_SHIFT,	SCI_CHARRIGHTEXTEND},
    {VK_RIGHT,		SCI_CTRL,	SCI_WORDRIGHT},
    {VK_RIGHT,		SCI_CSHIFT,	SCI_WORDRIGHTEXTEND},
    {VK_HOME, 		SCI_NORM, 	SCI_VCHOME},
    {VK_HOME, 		SCI_SHIFT, 	SCI_VCHOMEEXTEND},
    {VK_HOME, 		SCI_CTRL, 	SCI_DOCUMENTSTART},
    {VK_HOME, 		SCI_CSHIFT, 	SCI_DOCUMENTSTARTEXTEND},
    {VK_END,	 	SCI_NORM, 	SCI_LINEEND},
    {VK_END,	 	SCI_SHIFT, 	SCI_LINEENDEXTEND},
    {VK_END, 		SCI_CTRL, 	SCI_DOCUMENTEND},
    {VK_END, 		SCI_CSHIFT, 	SCI_DOCUMENTENDEXTEND},
    {VK_PRIOR,		SCI_NORM, 	SCI_PAGEUP},
    {VK_PRIOR,		SCI_SHIFT, 	SCI_PAGEUPEXTEND},
    {VK_NEXT, 		SCI_NORM, 	SCI_PAGEDOWN},
    {VK_NEXT, 		SCI_SHIFT, 	SCI_PAGEDOWNEXTEND},
    {VK_DELETE, 	SCI_NORM,	WM_CLEAR},
    {VK_DELETE, 	SCI_SHIFT,	WM_CUT},
    {VK_DELETE, 	SCI_CTRL,	SCI_DELWORDRIGHT},
    {VK_INSERT, 		SCI_NORM,	SCI_EDITTOGGLEOVERTYPE},
    {VK_INSERT, 		SCI_SHIFT,	WM_PASTE},
    {VK_INSERT, 		SCI_CTRL,	WM_COPY},
    {VK_ESCAPE,  	SCI_NORM,	SCI_CANCEL},
    {VK_BACK,		SCI_NORM, 	SCI_DELETEBACK},
    {VK_BACK,		SCI_SHIFT, 	SCI_DELETEBACK},
    {VK_BACK,		SCI_CTRL, 	SCI_DELWORDLEFT},
    {'Z', 			SCI_CTRL,	WM_UNDO},
    {'Y', 			SCI_CTRL,	SCI_REDO},
    {'X', 			SCI_CTRL,	WM_CUT},
    {'C', 			SCI_CTRL,	WM_COPY},
    {'V', 			SCI_CTRL,	WM_PASTE},
    {'A', 			SCI_CTRL,	SCI_SELECTALL},
    {VK_TAB,		SCI_NORM,	SCI_TAB},
    {VK_TAB,		SCI_SHIFT,	SCI_BACKTAB},
    {VK_RETURN, 	SCI_NORM,	SCI_NEWLINE},
    {VK_ADD, 		SCI_CTRL,	SCI_ZOOMIN},
    {VK_SUBTRACT,	SCI_CTRL,	SCI_ZOOMOUT},
    {VK_DIVIDE,	SCI_CTRL,	SCI_SETZOOM},
    //'L', 			SCI_CTRL,		SCI_FORMFEED,
    {'L', 			SCI_CTRL,	SCI_LINECUT},
    {'L', 			SCI_CSHIFT,	SCI_LINEDELETE},
    {'T', 			SCI_CTRL,	SCI_LINETRANSPOSE},
    {'U', 			SCI_CTRL,	SCI_LOWERCASE},
    {'U', 			SCI_CSHIFT,	SCI_UPPERCASE},
    {0,0,0},
};

<commit_msg>Added Alt+BackSpace as synonym for Undo.<commit_after>// Scintilla source code edit control
// KeyMap.cxx  - defines a mapping between keystrokes and commands
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include "Platform.h"

#include "Scintilla.h"

#include "KeyMap.h"

KeyMap::KeyMap() : kmap(0), len(0), alloc(0) {
	for (int i = 0; MapDefault[i].key; i++) {
		AssignCmdKey(MapDefault[i].key,
			MapDefault[i].modifiers,
             		MapDefault[i].msg);
	}
}

KeyMap::~KeyMap() {
	Clear();
}

void KeyMap::Clear() {
	delete []kmap;
	kmap = 0;
	len = 0;
	alloc = 0;
}

void KeyMap::AssignCmdKey(int key, int modifiers, UINT msg) {
	if ((len+1) >= alloc) {
		KeyToCommand *ktcNew = new KeyToCommand[alloc + 5];
		if (!ktcNew)
			return;
		for (int k=0;k<len;k++)
			ktcNew[k] = kmap[k];
		alloc += 5;
		delete []kmap;
		kmap = ktcNew;
	}
	for (int keyIndex = 0; keyIndex < len; keyIndex++) {
		if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) {
			kmap[keyIndex].msg = msg;
			return;
		}
	}
	kmap[len].key = key;
	kmap[len].modifiers = modifiers;
	kmap[len].msg = msg;
	len++;
}

UINT KeyMap::Find(int key, int modifiers) {
	for (int i=0; i < len; i++) {
		if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) {
			return kmap[i].msg;
		}
	}
	return 0;
}

KeyToCommand KeyMap::MapDefault[] = {
    {VK_DOWN,		SCI_NORM,	SCI_LINEDOWN},
    {VK_DOWN,		SCI_SHIFT,	SCI_LINEDOWNEXTEND},
    {VK_DOWN,		SCI_CTRL,	SCI_LINESCROLLDOWN},
    {VK_UP,			SCI_NORM,	SCI_LINEUP},
    {VK_UP,			SCI_SHIFT,	SCI_LINEUPEXTEND},
    {VK_UP,			SCI_CTRL,	SCI_LINESCROLLUP},
    {VK_LEFT,		SCI_NORM,	SCI_CHARLEFT},
    {VK_LEFT,		SCI_SHIFT,	SCI_CHARLEFTEXTEND},
    {VK_LEFT,		SCI_CTRL,	SCI_WORDLEFT},
    {VK_LEFT,		SCI_CSHIFT,	SCI_WORDLEFTEXTEND},
    {VK_RIGHT,		SCI_NORM,	SCI_CHARRIGHT},
    {VK_RIGHT,		SCI_SHIFT,	SCI_CHARRIGHTEXTEND},
    {VK_RIGHT,		SCI_CTRL,	SCI_WORDRIGHT},
    {VK_RIGHT,		SCI_CSHIFT,	SCI_WORDRIGHTEXTEND},
    {VK_HOME, 		SCI_NORM, 	SCI_VCHOME},
    {VK_HOME, 		SCI_SHIFT, 	SCI_VCHOMEEXTEND},
    {VK_HOME, 		SCI_CTRL, 	SCI_DOCUMENTSTART},
    {VK_HOME, 		SCI_CSHIFT, 	SCI_DOCUMENTSTARTEXTEND},
    {VK_END,	 	SCI_NORM, 	SCI_LINEEND},
    {VK_END,	 	SCI_SHIFT, 	SCI_LINEENDEXTEND},
    {VK_END, 		SCI_CTRL, 	SCI_DOCUMENTEND},
    {VK_END, 		SCI_CSHIFT, 	SCI_DOCUMENTENDEXTEND},
    {VK_PRIOR,		SCI_NORM, 	SCI_PAGEUP},
    {VK_PRIOR,		SCI_SHIFT, 	SCI_PAGEUPEXTEND},
    {VK_NEXT, 		SCI_NORM, 	SCI_PAGEDOWN},
    {VK_NEXT, 		SCI_SHIFT, 	SCI_PAGEDOWNEXTEND},
    {VK_DELETE, 	SCI_NORM,	WM_CLEAR},
    {VK_DELETE, 	SCI_SHIFT,	WM_CUT},
    {VK_DELETE, 	SCI_CTRL,	SCI_DELWORDRIGHT},
    {VK_INSERT, 		SCI_NORM,	SCI_EDITTOGGLEOVERTYPE},
    {VK_INSERT, 		SCI_SHIFT,	WM_PASTE},
    {VK_INSERT, 		SCI_CTRL,	WM_COPY},
    {VK_ESCAPE,  	SCI_NORM,	SCI_CANCEL},
    {VK_BACK,		SCI_NORM, 	SCI_DELETEBACK},
    {VK_BACK,		SCI_SHIFT, 	SCI_DELETEBACK},
    {VK_BACK,		SCI_CTRL, 	SCI_DELWORDLEFT},
    {VK_BACK, 		SCI_ALT,	WM_UNDO},
    {'Z', 			SCI_CTRL,	WM_UNDO},
    {'Y', 			SCI_CTRL,	SCI_REDO},
    {'X', 			SCI_CTRL,	WM_CUT},
    {'C', 			SCI_CTRL,	WM_COPY},
    {'V', 			SCI_CTRL,	WM_PASTE},
    {'A', 			SCI_CTRL,	SCI_SELECTALL},
    {VK_TAB,		SCI_NORM,	SCI_TAB},
    {VK_TAB,		SCI_SHIFT,	SCI_BACKTAB},
    {VK_RETURN, 	SCI_NORM,	SCI_NEWLINE},
    {VK_ADD, 		SCI_CTRL,	SCI_ZOOMIN},
    {VK_SUBTRACT,	SCI_CTRL,	SCI_ZOOMOUT},
    {VK_DIVIDE,	SCI_CTRL,	SCI_SETZOOM},
    //'L', 			SCI_CTRL,		SCI_FORMFEED,
    {'L', 			SCI_CTRL,	SCI_LINECUT},
    {'L', 			SCI_CSHIFT,	SCI_LINEDELETE},
    {'T', 			SCI_CTRL,	SCI_LINETRANSPOSE},
    {'U', 			SCI_CTRL,	SCI_LOWERCASE},
    {'U', 			SCI_CSHIFT,	SCI_UPPERCASE},
    {0,0,0},
};

<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexSQL.cxx
 ** Lexer for SQL.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char s[100];
	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		s[i + 1] = '\0';
	}
	char chAttr = SCE_C_IDENTIFIER;
	if (wordIsNumber)
		chAttr = SCE_C_NUMBER;
	else {
		if (keywords.InList(s))
			chAttr = SCE_C_WORD;
	}
	styler.ColourTo(end, chAttr);
}

static void ColouriseSQLDoc(unsigned int startPos, int length,
                            int initStyle, WordList *keywordlists[], Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold") != 0;
	bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0;
	int lineCurrent = styler.GetLine(startPos);
	int spaceFlags = 0;

	int state = initStyle;
	char chPrev = ' ';
	char chNext = styler[startPos];
	styler.StartSegment(startPos);
	unsigned int lengthDoc = startPos + length;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
			int lev = indentCurrent;
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
				if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				}
			}
			if (fold) {
				styler.SetLevel(lineCurrent, lev);
			}
		}

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (iswordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_C_WORD;
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_COMMENT;
			} else if (ch == '-' && chNext == '-') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_COMMENTLINE;
			} else if (ch == '#') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_COMMENTLINEDOC;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_CHARACTER;
			} else if (ch == '"') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_STRING;
			} else if (isoperator(ch)) {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_C_OPERATOR);
			}
		} else if (state == SCE_C_WORD) {
			if (!iswordchar(ch)) {
				classifyWordSQL(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_C_DEFAULT;
				if (ch == '/' && chNext == '*') {
					state = SCE_C_COMMENT;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '#') {
					state = SCE_C_COMMENTLINEDOC;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (ch == '"') {
					state = SCE_C_STRING;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
				}
			}
		} else {
			if (state == SCE_C_COMMENT) {
				if (ch == '/' && chPrev == '*') {
					if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&
					    (styler.GetStartSegment() == startPos)))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE || state == SCE_C_COMMENTLINEDOC) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i - 1, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_CHARACTER) {
				if (sqlBackslashEscapes && ch == '\\') {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (ch == '\'') {
					if (chNext == '\'') {
						i++;
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
						i++;
					}
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '"') {
					if (chNext == '"') {
						i++;
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
						i++;
					}
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			}
			if (state == SCE_C_DEFAULT) {    // One of the above succeeded
				if (ch == '/' && chNext == '*') {
					state = SCE_C_COMMENT;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '#') {
					state = SCE_C_COMMENTLINEDOC;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (ch == '"') {
					state = SCE_C_STRING;
				} else if (iswordstart(ch)) {
					state = SCE_C_WORD;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
				}
			}
		}
		chPrev = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);
}

static const char * const sqlWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", 0, sqlWordListDesc);
<commit_msg>Patch from Michael Owens to add a second set of keywords.<commit_after>// Scintilla source code edit control
/** @file LexSQL.cxx
 ** Lexer for SQL.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static void classifyWordSQL(unsigned int start, unsigned int end, WordList *keywordlists[], Accessor &styler) {
	char s[100];
	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		s[i + 1] = '\0';
	}

	WordList &keywords1 = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];

	char chAttr = SCE_C_IDENTIFIER;
	if (wordIsNumber)
		chAttr = SCE_C_NUMBER;
	else {
		if (keywords1.InList(s)) {
			chAttr = SCE_C_WORD;
		}

		if (keywords2.InList(s)) {
			chAttr = SCE_C_WORD2;
		}
	}
	styler.ColourTo(end, chAttr);
}

static void ColouriseSQLDoc(unsigned int startPos, int length,
                            int initStyle, WordList *keywordlists[], Accessor &styler) {

	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold") != 0;
	bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0;
	int lineCurrent = styler.GetLine(startPos);
	int spaceFlags = 0;

	int state = initStyle;
	char chPrev = ' ';
	char chNext = styler[startPos];
	styler.StartSegment(startPos);
	unsigned int lengthDoc = startPos + length;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
			int lev = indentCurrent;
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
				if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				}
			}
			if (fold) {
				styler.SetLevel(lineCurrent, lev);
			}
		}

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (iswordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_C_WORD;
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_COMMENT;
			} else if (ch == '-' && chNext == '-') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_COMMENTLINE;
			} else if (ch == '#') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_COMMENTLINEDOC;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_CHARACTER;
			} else if (ch == '"') {
				styler.ColourTo(i - 1, state);
				state = SCE_C_STRING;
			} else if (isoperator(ch)) {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_C_OPERATOR);
			}
		} else if (state == SCE_C_WORD) {
			if (!iswordchar(ch)) {
				classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler);
				state = SCE_C_DEFAULT;
				if (ch == '/' && chNext == '*') {
					state = SCE_C_COMMENT;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '#') {
					state = SCE_C_COMMENTLINEDOC;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (ch == '"') {
					state = SCE_C_STRING;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
				}
			}
		} else {
			if (state == SCE_C_COMMENT) {
				if (ch == '/' && chPrev == '*') {
					if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&
					    (styler.GetStartSegment() == startPos)))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE || state == SCE_C_COMMENTLINEDOC) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i - 1, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_CHARACTER) {
				if (sqlBackslashEscapes && ch == '\\') {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (ch == '\'') {
					if (chNext == '\'') {
						i++;
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
						i++;
					}
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '"') {
					if (chNext == '"') {
						i++;
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
						i++;
					}
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			}
			if (state == SCE_C_DEFAULT) {    // One of the above succeeded
				if (ch == '/' && chNext == '*') {
					state = SCE_C_COMMENT;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '#') {
					state = SCE_C_COMMENTLINEDOC;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (ch == '"') {
					state = SCE_C_STRING;
				} else if (iswordstart(ch)) {
					state = SCE_C_WORD;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
				}
			}
		}
		chPrev = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);
}

static const char * const sqlWordListDesc[] = {
	"Keywords",
	"Database Objects",
	0
};

LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", 0, sqlWordListDesc);
<|endoftext|>


<commit_before>//
//  Platform.cpp
//  CatchLib
//
//  Created by Sebastian Odbjer on 5/10/12.
//  Copyright (c) 2012 Catch22. All rights reserved.

#include "Platform.hpp"

Platform::Platform()
{

}

Platform::~Platform()
{

}

vector<PlatformBlock*> Platform::getPlatformBlocks()
{
	return platformblocks;
}

void Platform::addPlatformBlock(PlatformBlock* block)
{
	platformblocks.push_back(block);
}

void Platform::clearPlatformBlocks()
{
	platformblocks.clear();
}

Vector2d* Platform::startPoint()
{
	return platformblocks.front()->getStartVector();
}

Vector2d* Platform::endPoint()
{
	return platformblocks.back()->getEndVector();
}

<commit_msg>Added some comments on the code<commit_after>//
//  File:		Platform.cpp
//  Class:      Platform
//  Author:     Sebastian Odbjer
//              All code is my own except where credited to others.
//
//	Copyright (c) 2012 by Catch22. All Rights Reserved.
//  Date: 		05/10-2012

#include "Platform.hpp"

Platform::Platform()
{

}

Platform::~Platform()
{

}

vector<PlatformBlock*> Platform::getPlatformBlocks()
{
	return platformblocks;
}

void Platform::addPlatformBlock(PlatformBlock* block)
{
	platformblocks.push_back(block);
}

void Platform::clearPlatformBlocks()
{
	platformblocks.clear();
}

Vector2d* Platform::startPoint()
{
	return platformblocks.front()->getStartVector();
}

Vector2d* Platform::endPoint()
{
	return platformblocks.back()->getEndVector();
}

<|endoftext|>


<commit_before>#include "Shader.h"

const GLchar* vshader[] =
{
	"varying vec2 LVertexPos2D;"
	"void main() {"
	"	gl_Position = vec4( LVertexPos2D.x, LVertexPos2D.y, 0, 1 );"
	"}"
};

void Shader::Init() {
	// Create the program
	program = glCreateProgram();

	// Create and compile the vertex shader
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, vshader, NULL);
	glCompileShader(vertexShader);
	GLint length, result;
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &result);
	if (result == GL_FALSE) {
		glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &length);
		GLchar* log = new GLchar[length + 1];
		glGetShaderInfoLog(vertexShader, length, &result, log);
		std::string logStr(log);
		delete log;
		throw ShaderException(SHADER_COMPILE_FAILURE, "vertexShader", logStr);
	}

	glAttachShader(program, vertexShader);

	// Create Frame buffer and Render buffer
	glGenFramebuffers(1, &fbo);
	glGenRenderbuffers(1, &rb);

	quad.Init();
}

void Shader::SetShader(const std::string shaderSource, const std::string shaderName) {
	//TODO Detach current shader (if anything)

	// Create and compile the fragment shader
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	const char* src = shaderSource.c_str();
	const int srcLength = shaderSource.length();
	glShaderSource(fragmentShader, 1, &src, &srcLength);
	glCompileShader(fragmentShader);

	GLint length, result;
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &result);
	if (result == GL_FALSE) {
		glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length);
		GLchar* log = new GLchar[length + 1];
		glGetShaderInfoLog(fragmentShader, length, &result, log);
		std::string logStr(log);
		delete log;
		throw ShaderException(SHADER_COMPILE_FAILURE, shaderName, logStr);
	}

	glAttachShader(program, fragmentShader);
	glLinkProgram(program);

	glGetShaderiv(program, GL_LINK_STATUS, &result);
	if (result == GL_FALSE) {
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
		GLchar* log = new GLchar[length + 1];
		glGetProgramInfoLog(program, length, &result, log);
		std::string logStr(log);
		delete log;
		throw ShaderException(PROGRAM_LINK_FAILURE, "programLink", logStr);
	}

	vertAttrib = glGetAttribLocation(program, "LVertexPos2D");
}

void Shader::Render(const GLuint texture, const int w, const int h) {
	// Bind framebuffer
	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	glBindRenderbuffer(GL_RENDERBUFFER, rb);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);

	// Bind and format the given render texture
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

	// Filtering!
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	// Set the renderTexture as the FBO target
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

	// Draw on texture
	Draw();

	// De-bind FBO, Render buffer and texture
	glPopAttrib();
	glBindTexture(GL_TEXTURE_2D, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);
}

void Shader::Draw() {
	// Enable Shader
	glUseProgram(program);

	// Apply uniforms
	for (auto& item : uniforms) {
		GLint uniformLoc = GetUniform(item.first);
		item.second->Apply(uniformLoc);
	}

	// Render!
	quad.Draw(vertAttrib);

	// Disable shader
	glUseProgram(0);
}

GLint Shader::GetUniform(const std::string name) {
	if (uniformCache.find(name) == uniformCache.end()) {
		uniformCache[name] = glGetUniformLocation(program, name.c_str());
	}
	return uniformCache[name];
}

void Shader::Dispose() {
	for (auto& item : uniforms) {
		delete item.second;
	}
}<commit_msg>Fix vertex shader<commit_after>#include "Shader.h"

const GLchar* vshader[] =
{
	"attribute vec2 LVertexPos2D;"
	"void main() {"
	"	gl_Position = vec4( LVertexPos2D.x, LVertexPos2D.y, 0, 1 );"
	"}"
};

void Shader::Init() {
	// Create the program
	program = glCreateProgram();

	// Create and compile the vertex shader
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, vshader, NULL);
	glCompileShader(vertexShader);
	GLint length, result;
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &result);
	if (result == GL_FALSE) {
		glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &length);
		GLchar* log = new GLchar[length + 1];
		glGetShaderInfoLog(vertexShader, length, &result, log);
		std::string logStr(log);
		delete log;
		throw ShaderException(SHADER_COMPILE_FAILURE, "vertexShader", logStr);
	}

	glAttachShader(program, vertexShader);

	// Create Frame buffer and Render buffer
	glGenFramebuffers(1, &fbo);
	glGenRenderbuffers(1, &rb);

	quad.Init();
}

void Shader::SetShader(const std::string shaderSource, const std::string shaderName) {
	//TODO Detach current shader (if anything)

	// Create and compile the fragment shader
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	const char* src = shaderSource.c_str();
	const int srcLength = shaderSource.length();
	glShaderSource(fragmentShader, 1, &src, &srcLength);
	glCompileShader(fragmentShader);

	GLint length, result;
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &result);
	if (result == GL_FALSE) {
		glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length);
		GLchar* log = new GLchar[length + 1];
		glGetShaderInfoLog(fragmentShader, length, &result, log);
		std::string logStr(log);
		delete log;
		throw ShaderException(SHADER_COMPILE_FAILURE, shaderName, logStr);
	}

	glAttachShader(program, fragmentShader);
	glLinkProgram(program);

	glGetShaderiv(program, GL_LINK_STATUS, &result);
	if (result == GL_FALSE) {
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
		GLchar* log = new GLchar[length + 1];
		glGetProgramInfoLog(program, length, &result, log);
		std::string logStr(log);
		delete log;
		throw ShaderException(PROGRAM_LINK_FAILURE, "programLink", logStr);
	}

	vertAttrib = glGetAttribLocation(program, "LVertexPos2D");
}

void Shader::Render(const GLuint texture, const int w, const int h) {
	// Bind framebuffer
	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	glBindRenderbuffer(GL_RENDERBUFFER, rb);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);

	// Bind and format the given render texture
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

	// Filtering!
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	// Set the renderTexture as the FBO target
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

	// Draw on texture
	Draw();

	// De-bind FBO, Render buffer and texture
	glPopAttrib();
	glBindTexture(GL_TEXTURE_2D, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);
}

void Shader::Draw() {
	// Enable Shader
	glUseProgram(program);

	// Apply uniforms
	for (auto& item : uniforms) {
		GLint uniformLoc = GetUniform(item.first);
		item.second->Apply(uniformLoc);
	}

	// Render!
	quad.Draw(vertAttrib);

	// Disable shader
	glUseProgram(0);
}

GLint Shader::GetUniform(const std::string name) {
	if (uniformCache.find(name) == uniformCache.end()) {
		uniformCache[name] = glGetUniformLocation(program, name.c_str());
	}
	return uniformCache[name];
}

void Shader::Dispose() {
	for (auto& item : uniforms) {
		delete item.second;
	}
}<|endoftext|>


<commit_before>//Includes
#include <fstream>
#include <iostream>
#include <cvc4/cvc4.h>

//Header File
#include "../include/Solver.hpp"
#include "../include/Matrix.hpp"

using namespace CVC4;
using namespace std;

vector<int> Solver::find_x(std::vector<double>& coef, int n, int w, bool v)
{
    ExprManager em;
    SmtEngine smt(&em);

    vector<int> result;

    smt.setOption("incremental", SExpr("true"));
    smt.setOption("produce-models", SExpr("true"));
    GetModelCommand cExample = GetModelCommand();

    vector<Expr> A = Solver::Avector(coef, &em);

    vector<Expr> X = Solver::Xvector(n, w, &em);

    Expr X_EQ_1_OR_0 = Solver::XDomain   (X, &em);
    Expr almost_one  = Solver::almostOne (X, n, w, &em);
    Expr only_one    = Solver::onlyOne   (X, n, w, &em);
    Expr inequation  = Solver::inequation(X, A, &em);

    Expr assumptions = em.mkExpr(Kind::AND, X_EQ_1_OR_0, almost_one, only_one);
    smt.assertFormula(assumptions);

    smt.push();
    string isSat = smt.checkSat(inequation).toString();
    bool sat = isSat.compare("unsat");

    if(v)
    {
        cout << "\nThe inequation is "<< isSat;
        if(sat)
        {
            cout << " and a solution is:" << "\n";
            cExample.invoke(&smt);
            cExample.printResult(cout);
        }
        cout << "\n\n";

        cout << "The inequation:" << "\n";
        cout << inequation  << "\n\n";
        cout << "The Domain for the variables:" << "\n";
        cout << X_EQ_1_OR_0 << "\n\n";
        cout << "Almost one of the variables must be equal to 1:" << "\n";
        cout << almost_one  << "\n\n";
        cout << "Only one of the variables must be equal to 1:" << "\n";
        cout << only_one    << "\n\n";
    }

    if(sat)
        for(int i = 0; i < X.size(); i++)
            result.push_back(atoi(smt.getValue(X[i]).toString().c_str()));
    else
        result.push_back(-1);

    smt.pop();

    return result;

}

vector<Expr> Solver::Xvector(int n, int w, ExprManager* em)
{
    vector<Expr> X;

    for(int i = 0; i < w; i++)
        for(int j = 0; j < n; j++)
            X.push_back(em->mkVar("x" + to_string(i+1) + to_string(j+1), em->integerType()));

    return X;
}

vector<Expr> Solver::Avector(vector<double>& coef, ExprManager* em)
{
    vector<Expr> A;

    for(int i = 0; i < coef.size(); i++)
    {
        int temp = coef[i]*1000000;
        A.push_back(em->mkConst(Rational(temp,1000000)));
    }

    return A;
}

Expr Solver::XDomain(vector<Expr>& X, ExprManager* em)
{
    vector<Expr> X_domain;

    Expr one  = em->mkConst(Rational(1));
    Expr zero = em->mkConst(Rational(0));

    Expr Xi_EQ_one;
    Expr Xi_EQ_zero;
    Expr tmp;

    for(int i = 0; i < X.size(); i++)
    {
        Xi_EQ_one  = em->mkExpr(Kind::EQUAL, X[i], one );
        Xi_EQ_zero = em->mkExpr(Kind::EQUAL, X[i], zero);
        X_domain.push_back(em->mkExpr(Kind::OR, Xi_EQ_one, Xi_EQ_zero));
    }

    return em->mkExpr(Kind::AND, X_domain);
}

Expr Solver::almostOne(vector<Expr>& X, int n, int w, ExprManager* em)
{
    Expr one  = em->mkConst(Rational(1));
    vector<Expr> X_EQ_One;
    vector<Expr> X_AND;
    vector<Expr> X_OR;

    for(int i = 0; i < X.size(); i++)
        X_EQ_One.push_back(em->mkExpr(Kind::EQUAL, X[i], one));

    for(int i = 0; i < w; i++)
    {
        for(int j = 0; j < n ; j++)
            X_OR.push_back(X_EQ_One[i*n+j]);

        X_AND.push_back(em->mkExpr(Kind::OR, X_OR));
        X_OR.clear();
    }

    return em->mkExpr(Kind::AND, X_AND);

}

Expr Solver::onlyOne(vector<Expr>& X, int n, int w, ExprManager* em)
{
    Expr only_one;
    Expr one = em->mkConst(Rational(1));
    vector<Expr> X_NEQ_one;
    vector<Expr> X_AND;

    for(int i = 0; i < X.size(); i++)
        X_NEQ_one.push_back(em->mkExpr(Kind::DISTINCT, X[i], one));

    for(int i = 0; i < w; i++)
    {
        for(int j = i*n; j < i*n + n-1; j++)
            for (int k = j+1; k < i*n + n; k++)
                X_AND.push_back(em->mkExpr(Kind::OR,
                                           X_NEQ_one[j],
                                           X_NEQ_one[k]));
    }

    return em->mkExpr(Kind::AND, X_AND);
}

Expr Solver::inequation(vector<Expr>& X, vector<Expr>& A, ExprManager* em)
{

    Expr x_MUL_a;
    Expr zero = em->mkConst(Rational(0));
    Expr inequation;

    vector<Expr> Xi_MUL_Ai;

    Xi_MUL_Ai.push_back(A[0]);

    for(int i = 0; i < X.size(); i++)
    {
        x_MUL_a = em->mkExpr(Kind::MULT, X[i], A[i+1]);
        Xi_MUL_Ai.push_back(x_MUL_a);
    }

    inequation = em->mkExpr(Kind::PLUS, Xi_MUL_Ai);

    return em->mkExpr(Kind::GEQ, inequation, zero);
}
<commit_msg>renamed the class and move for the shr dir<commit_after><|endoftext|>


<commit_before>// Thread.cpp

#include "stateval/Thread.h"

/* STD */
#include <cassert>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

namespace Threading {

// ===============================================================================================
// = class Mutex
// ===============================================================================================
Mutex::Mutex()
: m_Mutex()
{
  const int rc(::pthread_mutex_init(&m_Mutex, NULL));
  assert(0 == rc);
}

Mutex::~Mutex()
{
  const int rc(::pthread_mutex_destroy(&m_Mutex));
  assert(0 == rc);
}

Mutex::EError Mutex::lock()
{
  int rc = ::pthread_mutex_lock(&m_Mutex);
  assert(0 == rc);
  return (0 == rc) ? eErrorOK : eErrorLock;
}

Mutex::EError Mutex::trylock()
{
  const int rc(::pthread_mutex_trylock(&m_Mutex));
  assert(EINVAL != rc);
  return (0     == rc) ? eErrorOK :
         (EBUSY == rc) ? eErrorLocked : eErrorLock;
}

Mutex::EError Mutex::unlock()
{
  const int rc(::pthread_mutex_unlock(&m_Mutex));
  assert(0 == rc);
  return (0 == rc) ? eErrorOK : eErrorUnlock;
}

// ===============================================================================================
// = class MutexGrabber
// ===============================================================================================
MutexGrabber::MutexGrabber(Mutex& inMutex)
: m_Mutex(inMutex)
{
  m_Mutex.lock();
}

MutexGrabber::~MutexGrabber()
{
  m_Mutex.unlock();
}

// ===============================================================================================
// = class Condition
// ===============================================================================================
Condition::Condition()
: m_Condition()
{
  const int rc(::pthread_cond_init(&m_Condition, NULL));
  assert(0 == rc);
}

Condition::~Condition()
{
  const int rc(::pthread_cond_destroy(&m_Condition));
  assert(0 == rc);
}

void Condition::signal()
{
  const int rc(::pthread_cond_signal(&m_Condition));
  assert(0 == rc);
}

void Condition::wait(Mutex& inMutex)
{
  int rc = ::pthread_cond_wait(&m_Condition, &inMutex.m_Mutex);
  assert(0 == rc);
}

// ===============================================================================================
// = class Condition
// ===============================================================================================
// public
Thread::Thread()
: m_AccessGuard()
, m_ThreadHd(0)
, m_State(eStopped)
{}

Thread::EError Thread::start()
{
  MutexGrabber grab(m_AccessGuard);
  if (eStopped == m_State)
  {
    m_State = eStarting;
    const int rc(::pthread_create(&m_ThreadHd, NULL, _run, this));
    assert(0==rc);

    // Was the cthread created successfully?
    if (rc != 0)
    {
      // No it didn't :-(
      m_State = eStopped; // cancel the starting state on failure
      return Thread::eErrorStart; // return 'failure'.
    }
  }
  return Thread::eErrorOK; // return 'success'.
}

Thread::EError Thread::cancel()
{
  MutexGrabber grab(m_AccessGuard);
  if (eRunning == m_State)
  {
    m_State = eStopping;
    m_AccessGuard.unlock();

    signal_cancel();

    const Thread::EError err(join());
    assert(eStopped == m_State);
    m_AccessGuard.lock();

    if (eErrorOK != err)
    {
      m_State = Thread::eStopped;
      return Thread::eErrorStop;
    }
  }
  m_AccessGuard.unlock();
  return Thread::eErrorOK;
}

Thread::EError Thread::join()
{
  const int rc(::pthread_join(m_ThreadHd, NULL));
  return (0 == rc) ? Thread::eErrorOK : Thread::eErrorJoin;
}

// public, static
void Thread::sleepMS(uint32_t inTimeMS)
{
  ::usleep(1000 * inTimeMS);
}

// Thread - static, private
void* Thread::_run(void* inArg)
{
  Thread* inst = reinterpret_cast<Thread*> (inArg);
  inst->m_AccessGuard.lock();
  inst->m_State = eRunning;
  inst->m_AccessGuard.unlock();

  inst->run();

  inst->m_AccessGuard.lock();
  inst->m_State = eStopped;
  inst->m_AccessGuard.unlock();
  return NULL;
}

} // end namespace Threading
<commit_msg>- compile again<commit_after>// Thread.cpp

#include "../include/stateval/Thread.h"

/* STD */
#include <cassert>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

namespace Threading {

// ===============================================================================================
// = class Mutex
// ===============================================================================================
Mutex::Mutex()
: m_Mutex()
{
  const int rc(::pthread_mutex_init(&m_Mutex, NULL));
  assert(0 == rc);
}

Mutex::~Mutex()
{
  const int rc(::pthread_mutex_destroy(&m_Mutex));
  assert(0 == rc);
}

Mutex::EError Mutex::lock()
{
  int rc = ::pthread_mutex_lock(&m_Mutex);
  assert(0 == rc);
  return (0 == rc) ? eErrorOK : eErrorLock;
}

Mutex::EError Mutex::trylock()
{
  const int rc(::pthread_mutex_trylock(&m_Mutex));
  assert(EINVAL != rc);
  return (0     == rc) ? eErrorOK :
         (EBUSY == rc) ? eErrorLocked : eErrorLock;
}

Mutex::EError Mutex::unlock()
{
  const int rc(::pthread_mutex_unlock(&m_Mutex));
  assert(0 == rc);
  return (0 == rc) ? eErrorOK : eErrorUnlock;
}

// ===============================================================================================
// = class MutexGrabber
// ===============================================================================================
MutexGrabber::MutexGrabber(Mutex& inMutex)
: m_Mutex(inMutex)
{
  m_Mutex.lock();
}

MutexGrabber::~MutexGrabber()
{
  m_Mutex.unlock();
}

// ===============================================================================================
// = class Condition
// ===============================================================================================
Condition::Condition()
: m_Condition()
{
  const int rc(::pthread_cond_init(&m_Condition, NULL));
  assert(0 == rc);
}

Condition::~Condition()
{
  const int rc(::pthread_cond_destroy(&m_Condition));
  assert(0 == rc);
}

void Condition::signal()
{
  const int rc(::pthread_cond_signal(&m_Condition));
  assert(0 == rc);
}

void Condition::wait(Mutex& inMutex)
{
  int rc = ::pthread_cond_wait(&m_Condition, &inMutex.m_Mutex);
  assert(0 == rc);
}

// ===============================================================================================
// = class Condition
// ===============================================================================================
// public
Thread::Thread()
: m_AccessGuard()
, m_ThreadHd(0)
, m_State(eStopped)
{}

Thread::EError Thread::start()
{
  MutexGrabber grab(m_AccessGuard);
  if (eStopped == m_State)
  {
    m_State = eStarting;
    const int rc(::pthread_create(&m_ThreadHd, NULL, _run, this));
    assert(0==rc);

    // Was the cthread created successfully?
    if (rc != 0)
    {
      // No it didn't :-(
      m_State = eStopped; // cancel the starting state on failure
      return Thread::eErrorStart; // return 'failure'.
    }
  }
  return Thread::eErrorOK; // return 'success'.
}

Thread::EError Thread::cancel()
{
  MutexGrabber grab(m_AccessGuard);
  if (eRunning == m_State)
  {
    m_State = eStopping;
    m_AccessGuard.unlock();

    signal_cancel();

    const Thread::EError err(join());
    assert(eStopped == m_State);
    m_AccessGuard.lock();

    if (eErrorOK != err)
    {
      m_State = Thread::eStopped;
      return Thread::eErrorStop;
    }
  }
  m_AccessGuard.unlock();
  return Thread::eErrorOK;
}

Thread::EError Thread::join()
{
  const int rc(::pthread_join(m_ThreadHd, NULL));
  return (0 == rc) ? Thread::eErrorOK : Thread::eErrorJoin;
}

// public, static
void Thread::sleepMS(uint32_t inTimeMS)
{
  ::usleep(1000 * inTimeMS);
}

// Thread - static, private
void* Thread::_run(void* inArg)
{
  Thread* inst = reinterpret_cast<Thread*> (inArg);
  inst->m_AccessGuard.lock();
  inst->m_State = eRunning;
  inst->m_AccessGuard.unlock();

  inst->run();

  inst->m_AccessGuard.lock();
  inst->m_State = eStopped;
  inst->m_AccessGuard.unlock();
  return NULL;
}

} // end namespace Threading
<|endoftext|>