<commit_before>/******************************************************************************
* Copyright (c) 2012, Howard Butler hobu.inc@gmail.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 Geo Consulting 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.
****************************************************************************/

#ifndef INCLUDED_METADATA_HPP
#define INCLUDED_METADATA_HPP

#include <pdal/pdal_internal.hpp>
#include <pdal/Options.hpp>
#include <pdal/Bounds.hpp>
#include <pdal/SpatialReference.hpp>

#include <boost/shared_array.hpp>
#include <boost/variant.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/blank.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <boost/optional.hpp>

#include <boost/algorithm/string.hpp>

#include <vector>
#include <map>

namespace pdal
{

/// ByteArray simply wrapps a std::vector<boost::uint8_t> such that it can then
/// be dumped to an ostream in a base64 encoding. For now, it makes a copy of the data
/// it is given, and should not be used for slinging big data around.
class PDAL_DLL ByteArray
{
public:

    /** @name Constructors
    */
    /// Constructs a ByteArray instance with the given array of data.
    ByteArray(std::vector<boost::uint8_t> const& data)
        : m_bytes(data)
    {
    }

    ByteArray()
    {
    }

    /// Copy constructor
    ByteArray(const ByteArray& rhs)
        : m_bytes(rhs.m_bytes)

    {
    }

    /// Assignment operator
    inline ByteArray& operator=(ByteArray const& rhs)
    {
        if (&rhs != this)
        {
            m_bytes = rhs.m_bytes;
        }
        return *this;
    }

    /** @name Data manipulation
    */
    /// resets the array
    inline void set(std::vector<boost::uint8_t> const& input)
    {
        m_bytes = input;
    }

    /// fetches a reference to the array
    inline std::vector<boost::uint8_t> const& get() const
    {
        return m_bytes;
    }

    /** @name private attributes
    */
private:

    std::vector<boost::uint8_t> m_bytes;
};

namespace metadata
{

typedef boost::uuids::uuid id;

enum Type
{
    /// boolean
    Boolean = 0,
    /// equivalent to int32_t
    SignedInteger,
    /// equivalent to uint32_t
    UnsignedInteger,
    /// equivalent to float
    Float,
    /// equivalent to double
    Double,
    /// equivalent to std::string
    String,
    /// raw binary data in the form std::vector<boost::uint8_t>
    Bytes,
    /// A pdal::Bounds instance
    Bounds,
    /// A pdal::SpatialReference instance
    SpatialReference,
    /// A boost::uuids::uuid instance
    UUID,
    /// A pdal::Metadata instance
    MData,
    /// Nothing
    Blank
};

}

/// metadata::Entry is a container for metadata entries that pdal::Stage and
/// pdal::PointBuffer carry around as part of their internal operations. Bits of
/// information might come from a pdal::Reader that opens a file, or a
/// pdal::Filter that processes as an intermediate stage, and
/// pdal::metadata::Entry is what is used to hold and pass those metadata
/// around.  pdal::metadata::Entry values must be of type
/// pdal::metadata::Variant and it is required that they are serializeable to
/// std::string.

/// pdal::metadata::Entry instances also carry with them a map of key/value
/// pairs called attributes that are metadata about the metadata entry. For
/// example, a LAS VLR might have a name of "classification", a pdal::ByteArray
/// for its data, and a set of attributes that are "userid":"4321" and
/// "vlrid":"1234". These other metadata may be useful given the context, and
/// any auxiliary data about the metadata entry should be provided via
/// attributes. It is up to you to determine where the line of attribute and new
/// metadata entry exists.
class PDAL_DLL Metadata
{
public:

    /** @name Constructors
    */
    /// Base constructor
    /// @param name entry name to use for this metadata entry
    Metadata();
    Metadata(std::string const& name);
    Metadata(Metadata const& other);

    template <typename T>
    Metadata(std::string const& name, const T& value, std::string const& description="")
    {
        setName(name);
        setDescription(description);
        setValue<T>(value);
    }

    template <typename T>
    void addMetadata(std::string const& name, const T& value, std::string const& description="");

    void addMetadata(  Metadata const& m);

    inline boost::property_tree::ptree toPTree() const
    {
        return m_tree;
    }

    /** @name entry type
    */
    /// returns the pdal::metadata::Type for the metadata entry
    inline metadata::Type getType() const
    {
        return static_cast<metadata::Type>(m_tree.get<boost::uint32_t>("type"));
    }

    /// sets the pdal::metadata::Type for the metadata entry
    /// @param t pdal::metadata::Type value for the entry
    inline void setType(metadata::Type t)
    {
        m_tree.put<boost::uint32_t>("type", static_cast<boost::uint32_t>(t));
        m_tree.put<std::string>("typename", getTypeName());
    }

    /// returns a std::string representation of the type
    std::string getTypeName() const;

    /** @name entry value
    */
    /// @param v value of type pdal::metadata::Variant to set for the entry
    template <class T> inline void setValue(T const& v);
    template <class T> inline T getValue() const { return m_tree.get<T>("value"); }

    /** @name entry name
    */
    /// returns the name for the metadata entry
    inline std::string getName() const
    {
        return m_tree.get<std::string>("name");
    }

    /// resets the name for the metadata entry
    /// @param name value to use for new name
    inline void setName(std::string const& name)
    {
        m_tree.put("name", name);
    }

    /** @name description
    */
    /// Overwrites the description given in the constructor
    /// @param description new value to use for the description of the Option
    inline void setDescription(const std::string& description)
    {
        m_tree.put("description", description);
    }

    /// @return the description of the Option
    inline std::string getDescription() const
    {
        return m_tree.get<std::string>("description");
    }

private:
    boost::property_tree::ptree m_tree;

};

template <>
inline void Metadata::setValue<bool>(bool const& v)
{
    setType(metadata::Boolean);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<std::string>(std::string const& v)
{
    setType(metadata::String);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::ByteArray>(pdal::ByteArray const& v)
{
    setType(metadata::Bytes);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<float>(float const& v)
{
    setType(metadata::Float);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<double>(double const& v)
{
    setType(metadata::Double);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::SpatialReference>(pdal::SpatialReference const& v)
{
    setType(metadata::SpatialReference);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::Bounds<double> >(pdal::Bounds<double> const& v)
{
    setType(metadata::Bounds);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint8_t>(boost::uint8_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint16_t>(boost::uint16_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint32_t>(boost::uint32_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint64_t>(boost::uint64_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int8_t>(boost::int8_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int16_t>(boost::int16_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int32_t>(boost::int32_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int64_t>(boost::int64_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uuids::uuid>(boost::uuids::uuid const& v)
{
    setType(metadata::UUID);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::Metadata>(pdal::Metadata const& v)
{
    setType(metadata::MData);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::blank>(boost::blank const& v)
{
    setType(metadata::Blank);
    m_tree.put("value",v);
}

inline void Metadata::addMetadata(  Metadata const& m)
{

    std::string n = boost::algorithm::ireplace_all_copy(m.getName(), ".", "_");
    m_tree.add_child("entries."+n, m.toPTree());
}

template <typename T>
inline void Metadata::addMetadata(  std::string const& name,
                                    T const& value,
                                    std::string const& description)
{
    Metadata m(name, value, description);
    addMetadata(m);
}

} // namespace pdal

namespace std
{

///
extern PDAL_DLL std::ostream& operator<<(std::ostream& ostr, const pdal::ByteArray& output);
extern PDAL_DLL std::istream& operator>>(std::istream& istr, pdal::ByteArray& output);
extern PDAL_DLL std::ostream& operator<<(std::ostream& ostr, const pdal::Metadata& m);

// extern PDAL_DLL std::ostream& operator<<(std::ostream& ostr, const pdal::Metadata& metadata);
}

#endif
<commit_msg>add getValueOptional that reaches through the 'entries' tree to get entries with a given path<commit_after>/******************************************************************************
* Copyright (c) 2012, Howard Butler hobu.inc@gmail.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 Geo Consulting 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.
****************************************************************************/

#ifndef INCLUDED_METADATA_HPP
#define INCLUDED_METADATA_HPP

#include <pdal/pdal_internal.hpp>
#include <pdal/Options.hpp>
#include <pdal/Bounds.hpp>
#include <pdal/SpatialReference.hpp>

#include <boost/shared_array.hpp>
#include <boost/variant.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/blank.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <boost/optional.hpp>

#include <boost/algorithm/string.hpp>

#include <vector>
#include <map>

namespace pdal
{

/// ByteArray simply wrapps a std::vector<boost::uint8_t> such that it can then
/// be dumped to an ostream in a base64 encoding. For now, it makes a copy of the data
/// it is given, and should not be used for slinging big data around.
class PDAL_DLL ByteArray
{
public:

    /** @name Constructors
    */
    /// Constructs a ByteArray instance with the given array of data.
    ByteArray(std::vector<boost::uint8_t> const& data)
        : m_bytes(data)
    {
    }

    ByteArray()
    {
    }

    /// Copy constructor
    ByteArray(const ByteArray& rhs)
        : m_bytes(rhs.m_bytes)

    {
    }

    /// Assignment operator
    inline ByteArray& operator=(ByteArray const& rhs)
    {
        if (&rhs != this)
        {
            m_bytes = rhs.m_bytes;
        }
        return *this;
    }

    /** @name Data manipulation
    */
    /// resets the array
    inline void set(std::vector<boost::uint8_t> const& input)
    {
        m_bytes = input;
    }

    /// fetches a reference to the array
    inline std::vector<boost::uint8_t> const& get() const
    {
        return m_bytes;
    }

    /** @name private attributes
    */
private:

    std::vector<boost::uint8_t> m_bytes;
};

namespace metadata
{

typedef boost::uuids::uuid id;

enum Type
{
    /// boolean
    Boolean = 0,
    /// equivalent to int32_t
    SignedInteger,
    /// equivalent to uint32_t
    UnsignedInteger,
    /// equivalent to float
    Float,
    /// equivalent to double
    Double,
    /// equivalent to std::string
    String,
    /// raw binary data in the form std::vector<boost::uint8_t>
    Bytes,
    /// A pdal::Bounds instance
    Bounds,
    /// A pdal::SpatialReference instance
    SpatialReference,
    /// A boost::uuids::uuid instance
    UUID,
    /// A pdal::Metadata instance
    MData,
    /// Nothing
    Blank
};

}

/// metadata::Entry is a container for metadata entries that pdal::Stage and
/// pdal::PointBuffer carry around as part of their internal operations. Bits of
/// information might come from a pdal::Reader that opens a file, or a
/// pdal::Filter that processes as an intermediate stage, and
/// pdal::metadata::Entry is what is used to hold and pass those metadata
/// around.  pdal::metadata::Entry values must be of type
/// pdal::metadata::Variant and it is required that they are serializeable to
/// std::string.

/// pdal::metadata::Entry instances also carry with them a map of key/value
/// pairs called attributes that are metadata about the metadata entry. For
/// example, a LAS VLR might have a name of "classification", a pdal::ByteArray
/// for its data, and a set of attributes that are "userid":"4321" and
/// "vlrid":"1234". These other metadata may be useful given the context, and
/// any auxiliary data about the metadata entry should be provided via
/// attributes. It is up to you to determine where the line of attribute and new
/// metadata entry exists.
class PDAL_DLL Metadata
{
public:

    /** @name Constructors
    */
    /// Base constructor
    /// @param name entry name to use for this metadata entry
    Metadata();
    Metadata(std::string const& name);
    Metadata(Metadata const& other);

    template <typename T>
    Metadata(std::string const& name, const T& value, std::string const& description="")
    {
        setName(name);
        setDescription(description);
        setValue<T>(value);
    }

    template <typename T>
    void addMetadata(std::string const& name, const T& value, std::string const& description="");

    void addMetadata(  Metadata const& m);

    inline boost::property_tree::ptree toPTree() const
    {
        return m_tree;
    }

    /** @name entry type
    */
    /// returns the pdal::metadata::Type for the metadata entry
    inline metadata::Type getType() const
    {
        return static_cast<metadata::Type>(m_tree.get<boost::uint32_t>("type"));
    }

    /// sets the pdal::metadata::Type for the metadata entry
    /// @param t pdal::metadata::Type value for the entry
    inline void setType(metadata::Type t)
    {
        m_tree.put<boost::uint32_t>("type", static_cast<boost::uint32_t>(t));
        m_tree.put<std::string>("typename", getTypeName());
    }

    /// returns a std::string representation of the type
    std::string getTypeName() const;

    /** @name entry value
    */
    /// @param v value of type pdal::metadata::Variant to set for the entry
    template <class T> inline void setValue(T const& v);
    template <class T> inline T getValue() const { return m_tree.get<T>("value"); }
    template <class T> inline T getValue(std::string const& path) const { return m_tree.get<T>("entries."+path+".value"); }
    template <class T> inline boost::optional<T> getValueOptional(std::string const& path) const
    {
        return m_tree.get_optional<T>("entries." + path+".value");
    }

    /** @name entry name
    */
    /// returns the name for the metadata entry
    inline std::string getName() const
    {
        return m_tree.get<std::string>("name");
    }

    /// resets the name for the metadata entry
    /// @param name value to use for new name
    inline void setName(std::string const& name)
    {
        m_tree.put("name", name);
    }

    /** @name description
    */
    /// Overwrites the description given in the constructor
    /// @param description new value to use for the description of the Option
    inline void setDescription(const std::string& description)
    {
        m_tree.put("description", description);
    }

    /// @return the description of the Option
    inline std::string getDescription() const
    {
        return m_tree.get<std::string>("description");
    }

private:
    boost::property_tree::ptree m_tree;

};

template <>
inline void Metadata::setValue<bool>(bool const& v)
{
    setType(metadata::Boolean);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<std::string>(std::string const& v)
{
    setType(metadata::String);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::ByteArray>(pdal::ByteArray const& v)
{
    setType(metadata::Bytes);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<float>(float const& v)
{
    setType(metadata::Float);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<double>(double const& v)
{
    setType(metadata::Double);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::SpatialReference>(pdal::SpatialReference const& v)
{
    setType(metadata::SpatialReference);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::Bounds<double> >(pdal::Bounds<double> const& v)
{
    setType(metadata::Bounds);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint8_t>(boost::uint8_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint16_t>(boost::uint16_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint32_t>(boost::uint32_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uint64_t>(boost::uint64_t const& v)
{
    setType(metadata::UnsignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int8_t>(boost::int8_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int16_t>(boost::int16_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int32_t>(boost::int32_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::int64_t>(boost::int64_t const& v)
{
    setType(metadata::SignedInteger);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::uuids::uuid>(boost::uuids::uuid const& v)
{
    setType(metadata::UUID);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<pdal::Metadata>(pdal::Metadata const& v)
{
    setType(metadata::MData);
    m_tree.put("value",v);
}

template <>
inline void Metadata::setValue<boost::blank>(boost::blank const& v)
{
    setType(metadata::Blank);
    m_tree.put("value",v);
}

inline void Metadata::addMetadata(  Metadata const& m)
{

    std::string n = boost::algorithm::ireplace_all_copy(m.getName(), ".", "_");
    m_tree.add_child("entries."+n, m.toPTree());
}

template <typename T>
inline void Metadata::addMetadata(  std::string const& name,
                                    T const& value,
                                    std::string const& description)
{
    Metadata m(name, value, description);
    addMetadata(m);
}

} // namespace pdal

namespace std
{

///
extern PDAL_DLL std::ostream& operator<<(std::ostream& ostr, const pdal::ByteArray& output);
extern PDAL_DLL std::istream& operator>>(std::istream& istr, pdal::ByteArray& output);
extern PDAL_DLL std::ostream& operator<<(std::ostream& ostr, const pdal::Metadata& m);

// extern PDAL_DLL std::ostream& operator<<(std::ostream& ostr, const pdal::Metadata& metadata);
}

#endif
<|endoftext|>


<commit_before>#ifndef SHRIMP_SHRIMP_HPP
#define SHRIMP_SHRIMP_HPP

#define wxNO__T

#pragma clang diagnostic push
// TODO: Ignore -pedantic
#pragma clang diagnostic ignored "-Wall"
#pragma clang diagnostic ignored "-Wextra"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wlong-long"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
# include <wx/wx.h>
#endif
#include <wx/glcanvas.h>
#include <wx/toolbar.h>
#pragma clang diagnostic pop

#include <iostream>

namespace shrimp {

class gl_canvas : public wxGLCanvas {
public:
  gl_canvas(wxWindow* parent)
    : wxGLCanvas(parent,
                 wxID_ANY,
                 nullptr,
                 wxDefaultPosition,
                 wxDefaultSize,
                 0,
                 wxGLCanvasName,
                 wxNullPalette) {
  }
};

class frame : public wxFrame {
private:
  gl_canvas* gl_canvas_;
public:
  frame()
    : wxFrame(nullptr,
              wxID_ANY,
              wxT("Shrimp")),
      gl_canvas_(nullptr) {
    {
      wxMenu* file_menu = new wxMenu();
      file_menu->Append(wxID_EXIT, wxT("E&xit\tALT-X"));
      wxMenuBar* menu_bar = new wxMenuBar();
      menu_bar->Append(file_menu, wxT("&File"));
      this->SetMenuBar(menu_bar);
    }
    {
      long style = wxTB_TOP;
      wxToolBar* tool_bar = this->CreateToolBar(style);
      // TODO: Modify tool_bar
      tool_bar->Realize();
    }
    this->gl_canvas_ = new gl_canvas(this);
  }
  virtual void
  OnExit(wxCommandEvent&) {
    this->Close(true);
  }
private:
  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(frame, wxFrame)
EVT_MENU(wxID_EXIT, frame::OnExit)
END_EVENT_TABLE()

class app : public wxApp {
public:
  virtual bool
  OnInit() {
    frame* f = new frame();
    f->Show(true);
    this->SetTopWindow(f);
    return true;
  }
};

}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-prototypes"
IMPLEMENT_APP(shrimp::app);
#pragma clang diagnostic pop

#endif
<commit_msg>Modified using wxGLCanvas<commit_after>#ifndef SHRIMP_SHRIMP_HPP
#define SHRIMP_SHRIMP_HPP

#define wxNO__T

#pragma clang diagnostic push
// TODO: Ignore -pedantic
#pragma clang diagnostic ignored "-Wall"
#pragma clang diagnostic ignored "-Wextra"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wlong-long"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
# include <wx/wx.h>
#endif
#include <wx/glcanvas.h>
#include <wx/toolbar.h>
#pragma clang diagnostic pop

#include <iostream>

namespace shrimp {

class gl_canvas : public wxGLCanvas {
private:
  wxGLContext* context_;
public:
  gl_canvas(wxWindow* parent)
    : wxGLCanvas(parent,
                 wxID_ANY,
                 nullptr,
                 wxDefaultPosition,
                 wxDefaultSize,
                 0,
                 wxGLCanvasName,
                 wxNullPalette),
      context_(new wxGLContext(this)) {
  }
  void
  OnPaint(wxPaintEvent&) {
    wxPaintDC dc(this);
    this->SetCurrent(*this->context_);
    ::glClearColor(0, 0, 0, 0);
    ::glClear(GL_COLOR_BUFFER_BIT);
    ::glFlush();
    this->SwapBuffers();
  }
private:
  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(gl_canvas, wxGLCanvas)
EVT_PAINT(gl_canvas::OnPaint)
END_EVENT_TABLE()

class frame : public wxFrame {
private:
  gl_canvas* gl_canvas_;
public:
  frame()
    : wxFrame(nullptr,
              wxID_ANY,
              wxT("Shrimp")),
      gl_canvas_(nullptr) {
    {
      wxMenu* file_menu = new wxMenu();
      file_menu->Append(wxID_EXIT, wxT("E&xit\tALT-X"));
      wxMenuBar* menu_bar = new wxMenuBar();
      menu_bar->Append(file_menu, wxT("&File"));
      this->SetMenuBar(menu_bar);
    }
    {
      long style = wxTB_TOP;
      wxToolBar* tool_bar = this->CreateToolBar(style);
      // TODO: Modify tool_bar
      tool_bar->Realize();
    }
    this->gl_canvas_ = new gl_canvas(this);
  }
  virtual void
  OnExit(wxCommandEvent&) {
    this->Close(true);
  }
private:
  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(frame, wxFrame)
EVT_MENU(wxID_EXIT, frame::OnExit)
END_EVENT_TABLE()

class app : public wxApp {
public:
  virtual bool
  OnInit() {
    frame* f = new frame();
    f->Show(true);
    this->SetTopWindow(f);
    return true;
  }
};

}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-prototypes"
IMPLEMENT_APP(shrimp::app);
#pragma clang diagnostic pop

#endif
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 "rc_loss_alarm.h"

#include <px4_defines.h>

#include <drivers/drv_hrt.h>
#include <errno.h>
#include <stdint.h>

#include <uORB/topics/tune_control.h>

// Init static members
work_s RC_Loss_Alarm::_work = {};
bool RC_Loss_Alarm::_was_armed = false;
bool RC_Loss_Alarm::_had_rc = false;
orb_advert_t RC_Loss_Alarm::_tune_control_pub = nullptr;

RC_Loss_Alarm::RC_Loss_Alarm()
{
}

RC_Loss_Alarm::~RC_Loss_Alarm()
{
	work_cancel(LPWORK, &_work);

	orb_unsubscribe(_vehicle_status_sub);

	orb_unadvertise(_tune_control_pub);
}

/** @see ModuleBase */
int RC_Loss_Alarm::task_spawn(int argc, char *argv[])
{
	// Instantiate task
	RC_Loss_Alarm *rc_loss_alarm = nullptr;

	if (_object == nullptr) {
		rc_loss_alarm = new RC_Loss_Alarm();

		if (rc_loss_alarm == nullptr) {
			PX4_ERR("failed to start flow");
			return PX4_ERROR;
		}
	}

	_object = rc_loss_alarm;

	// schedule a cycle to start things
	int ret = work_queue(LPWORK, &_work,
			     (worker_t)&RC_Loss_Alarm::cycle_trampoline, rc_loss_alarm, 0);

	if (ret < 0) {
		return ret;
	}

	// Since this task runs on the work-queue rather than in a separate thread,
	// we specify the workqueue task_id
	_task_id = task_id_is_work_queue;

	// wait until task is up & running (the mode_* commands depend on it)
	if (wait_until_running() < 0) {
		return -1;
	}

	return PX4_OK;
}

/** @see ModuleBase */
int RC_Loss_Alarm::custom_command(int argc, char *argv[])
{
	if (!strcmp(argv[0], "test")) {
		RC_Loss_Alarm::pub_tune();
		return PX4_OK;

	} else if (!strcmp(argv[0], "reset")) {
		return RC_Loss_Alarm::reset_module();
	}

	return print_usage("unknown command");
}

/** @see ModuleBase */
int RC_Loss_Alarm::print_usage(const char *reason)
{
	if (reason) {
		PX4_WARN("%s\n", reason);
	}

	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
### Description
RC Loss Alarm plays a loud error tune in the event that the drone loses RC
link after disarming. Ideal for finding a lost drone. The RC Loss Module
subscribes to the vehicle_status topic and checks the armed state as well as
the rc_signal_lost flag. The RC Loss alarm will only be triggered if
rc_signal_lost flag was false at least once at some point (i.e. if an RC is
connected).
### Example
The module is typically started with:
rc_loss_alarm start
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("rc_loss_alarm", "driver");
	PRINT_MODULE_USAGE_COMMAND_DESCR("start",  "Start the task");
	PRINT_MODULE_USAGE_COMMAND_DESCR("stop",   "Stop the task");
	PRINT_MODULE_USAGE_COMMAND_DESCR("status", "Display running status of task");
	PRINT_MODULE_USAGE_COMMAND_DESCR("test",   "Start alarm tune, can be stopped with 'reset'");
	PRINT_MODULE_USAGE_COMMAND_DESCR("reset",  "Resets internal state and stops an eventual alarm");
	return PX4_OK;
}

void RC_Loss_Alarm::cycle_trampoline(void *arg)
{
	RC_Loss_Alarm *dev = reinterpret_cast<RC_Loss_Alarm *>(arg);
	dev->cycle();
}

void RC_Loss_Alarm::cycle()
{
  // Subscribe if necessary
  if(_vehicle_status_sub == -1){
    _vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
  }

  // Check armed status
  bool updated = false;

  orb_check(_vehicle_status_sub, &updated);
  if(updated){
    orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);

    if (!_was_armed &&
        _vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED){

      _was_armed = true;  // Once true, impossible to go back to false
    }

    if (!_had_rc && !_vehicle_status.rc_signal_lost){

      _had_rc = true;
    }

    if (_was_armed && _had_rc && _vehicle_status.rc_signal_lost &&
        _vehicle_status.arming_state != vehicle_status_s::ARMING_STATE_ARMED){

      pub_tune();
    }
  }

  // Schedule next cycle unless module is shutting down
	if (!should_exit()) {
			work_queue(LPWORK, &_work, (worker_t)&RC_Loss_Alarm::cycle_trampoline, this,
				   USEC2TICK(UPDATE_RATE));
	}
}

void RC_Loss_Alarm::pub_tune()
{
  struct tune_control_s tune_control = {};
	tune_control.tune_id = static_cast<int>(TuneID::ERROR_TUNE);
	tune_control.strength = tune_control_s::STRENGTH_MAX;
	tune_control.tune_override = 1;
	tune_control.timestamp = hrt_absolute_time();

  if (_tune_control_pub == nullptr) {
    _tune_control_pub = orb_advertise(ORB_ID(tune_control), &tune_control);
  }else{
    orb_publish(ORB_ID(tune_control), _tune_control_pub, &tune_control);
  }
}

void RC_Loss_Alarm::stop_tune()
{
  struct tune_control_s tune_control = {};
  tune_control.tune_id = static_cast<int>(TuneID::CUSTOM);
  tune_control.frequency = 0;
  tune_control.duration = 0;
  tune_control.silence = 0;
  tune_control.tune_override = true;

  if (_tune_control_pub == nullptr) {
    _tune_control_pub = orb_advertise(ORB_ID(tune_control), &tune_control);
  }else{
    orb_publish(ORB_ID(tune_control), _tune_control_pub, &tune_control);
  }
}

int RC_Loss_Alarm::reset_module(){
  RC_Loss_Alarm::_was_armed = false;
  RC_Loss_Alarm::_had_rc = false;
  RC_Loss_Alarm::stop_tune();
  return PX4_OK;
}

// module 'main' command
extern "C" __EXPORT int rc_loss_alarm_main(int argc, char *argv[]);
int rc_loss_alarm_main(int argc, char *argv[])
{
	return RC_Loss_Alarm::main(argc, argv);
}
<commit_msg>rc_loss_alarm: replaced hard with soft tabs<commit_after>/****************************************************************************
 *
 *	 Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *		notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 "rc_loss_alarm.h"

#include <px4_defines.h>

#include <drivers/drv_hrt.h>
#include <errno.h>
#include <stdint.h>

#include <uORB/topics/tune_control.h>

// Init static members
work_s RC_Loss_Alarm::_work = {};
bool RC_Loss_Alarm::_was_armed = false;
bool RC_Loss_Alarm::_had_rc = false;
orb_advert_t RC_Loss_Alarm::_tune_control_pub = nullptr;

RC_Loss_Alarm::RC_Loss_Alarm()
{
}

RC_Loss_Alarm::~RC_Loss_Alarm()
{
	work_cancel(LPWORK, &_work);

	orb_unsubscribe(_vehicle_status_sub);

	orb_unadvertise(_tune_control_pub);
}

/** @see ModuleBase */
int RC_Loss_Alarm::task_spawn(int argc, char *argv[])
{
	// Instantiate task
	RC_Loss_Alarm *rc_loss_alarm = nullptr;

	if (_object == nullptr) {
		rc_loss_alarm = new RC_Loss_Alarm();

		if (rc_loss_alarm == nullptr) {
			PX4_ERR("failed to start flow");
			return PX4_ERROR;
		}
	}

	_object = rc_loss_alarm;

	// schedule a cycle to start things
	int ret = work_queue(LPWORK, &_work,
			     (worker_t)&RC_Loss_Alarm::cycle_trampoline, rc_loss_alarm, 0);

	if (ret < 0) {
		return ret;
	}

	// Since this task runs on the work-queue rather than in a separate thread,
	// we specify the workqueue task_id
	_task_id = task_id_is_work_queue;

	// wait until task is up & running (the mode_* commands depend on it)
	if (wait_until_running() < 0) {
		return -1;
	}

	return PX4_OK;
}

/** @see ModuleBase */
int RC_Loss_Alarm::custom_command(int argc, char *argv[])
{
	if (!strcmp(argv[0], "test")) {
		RC_Loss_Alarm::pub_tune();
		return PX4_OK;

	} else if (!strcmp(argv[0], "reset")) {
		return RC_Loss_Alarm::reset_module();
	}

	return print_usage("unknown command");
}

/** @see ModuleBase */
int RC_Loss_Alarm::print_usage(const char *reason)
{
	if (reason) {
		PX4_WARN("%s\n", reason);
	}

	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
### Description
RC Loss Alarm plays a loud error tune in the event that the drone loses RC
link after disarming. Ideal for finding a lost drone. The RC Loss Module
subscribes to the vehicle_status topic and checks the armed state as well as
the rc_signal_lost flag. The RC Loss alarm will only be triggered if
rc_signal_lost flag was false at least once at some point (i.e. if an RC is
connected).
### Example
The module is typically started with:
rc_loss_alarm start
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("rc_loss_alarm", "driver");
	PRINT_MODULE_USAGE_COMMAND_DESCR("start",  "Start the task");
	PRINT_MODULE_USAGE_COMMAND_DESCR("stop",   "Stop the task");
	PRINT_MODULE_USAGE_COMMAND_DESCR("status", "Display running status of task");
	PRINT_MODULE_USAGE_COMMAND_DESCR("test",   "Start alarm tune, can be stopped with 'reset'");
	PRINT_MODULE_USAGE_COMMAND_DESCR("reset",  "Resets internal state and stops an eventual alarm");
	return PX4_OK;
}

void RC_Loss_Alarm::cycle_trampoline(void *arg)
{
	RC_Loss_Alarm *dev = reinterpret_cast<RC_Loss_Alarm *>(arg);
	dev->cycle();
}

void RC_Loss_Alarm::cycle()
{
	// Subscribe if necessary
	if(_vehicle_status_sub == -1){
		_vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
	}

	// Check armed status
	bool updated = false;

	orb_check(_vehicle_status_sub, &updated);
	if(updated){
		orb_copy(ORB_ID(vehicle_status), _vehicle_status_sub, &_vehicle_status);

		if (!_was_armed &&
				_vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED){

			_was_armed = true;	// Once true, impossible to go back to false
		}

		if (!_had_rc && !_vehicle_status.rc_signal_lost){

			_had_rc = true;
		}

		if (_was_armed && _had_rc && _vehicle_status.rc_signal_lost &&
				_vehicle_status.arming_state != vehicle_status_s::ARMING_STATE_ARMED){

			pub_tune();
		}
	}

	// Schedule next cycle unless module is shutting down
	if (!should_exit()) {
			work_queue(LPWORK, &_work, (worker_t)&RC_Loss_Alarm::cycle_trampoline, this,
					 USEC2TICK(UPDATE_RATE));
	}
}

void RC_Loss_Alarm::pub_tune()
{
	struct tune_control_s tune_control = {};
	tune_control.tune_id = static_cast<int>(TuneID::ERROR_TUNE);
	tune_control.strength = tune_control_s::STRENGTH_MAX;
	tune_control.tune_override = 1;
	tune_control.timestamp = hrt_absolute_time();

	if (_tune_control_pub == nullptr) {
		_tune_control_pub = orb_advertise(ORB_ID(tune_control), &tune_control);
	}else{
		orb_publish(ORB_ID(tune_control), _tune_control_pub, &tune_control);
	}
}

void RC_Loss_Alarm::stop_tune()
{
	struct tune_control_s tune_control = {};
	tune_control.tune_id = static_cast<int>(TuneID::CUSTOM);
	tune_control.frequency = 0;
	tune_control.duration = 0;
	tune_control.silence = 0;
	tune_control.tune_override = true;

	if (_tune_control_pub == nullptr) {
		_tune_control_pub = orb_advertise(ORB_ID(tune_control), &tune_control);
	}else{
		orb_publish(ORB_ID(tune_control), _tune_control_pub, &tune_control);
	}
}

int RC_Loss_Alarm::reset_module(){
	RC_Loss_Alarm::_was_armed = false;
	RC_Loss_Alarm::_had_rc = false;
	RC_Loss_Alarm::stop_tune();
	return PX4_OK;
}

// module 'main' command
extern "C" __EXPORT int rc_loss_alarm_main(int argc, char *argv[]);
int rc_loss_alarm_main(int argc, char *argv[])
{
	return RC_Loss_Alarm::main(argc, argv);
}
<|endoftext|>


<commit_before>/*!
    \file latch.inl
    \brief Latch synchronization primitive inline implementation
    \author Ivan Shynkarenka
    \date 25.03.2016
    \copyright MIT License
*/

namespace CppCommon {

inline Latch::Latch(int threads) noexcept : _generation(0), _threads(threads)
{
    assert((threads > 0) && "Latch threads counter must be greater than zero!");
}

inline bool Latch::TryWaitFor(int64_t nanoseconds) noexcept
{
    return TryWaitFor(std::chrono::nanoseconds(nanoseconds));
}

template <class Rep, class Period>
inline bool Latch::TryWaitFor(const std::chrono::duration<Rep, Period>& duration) noexcept
{
    std::unique_lock<std::mutex> lock(_mutex);

    // Check the latch threads counter value
    if (_threads == 0)
        return true;

    // Remember the current latch generation
    int generation = _generation;

    // Wait for the next latch generation
    return _cond.wait_for(lock, duration, [=, this]() { return generation != _generation; });
}

template <class Clock, class Duration>
inline bool Latch::TryWaitUntil(const std::chrono::time_point<Clock, Duration>& timestamp) noexcept
{
    std::unique_lock<std::mutex> lock(_mutex);

    // Check the latch threads counter value
    if (_threads == 0)
        return true;

    // Remember the current latch generation
    int generation = _generation;

    // Wait for the next latch generation
    return _cond.wait_until(lock, timestamp, [=, this]() { return generation != _generation; });
}

} // namespace CppCommon
<commit_msg>Fix linux build<commit_after>/*!
    \file latch.inl
    \brief Latch synchronization primitive inline implementation
    \author Ivan Shynkarenka
    \date 25.03.2016
    \copyright MIT License
*/

namespace CppCommon {

inline Latch::Latch(int threads) noexcept : _generation(0), _threads(threads)
{
    assert((threads > 0) && "Latch threads counter must be greater than zero!");
}

inline bool Latch::TryWaitFor(int64_t nanoseconds) noexcept
{
    return TryWaitFor(std::chrono::nanoseconds(nanoseconds));
}

template <class Rep, class Period>
inline bool Latch::TryWaitFor(const std::chrono::duration<Rep, Period>& duration) noexcept
{
    std::unique_lock<std::mutex> lock(_mutex);

    // Check the latch threads counter value
    if (_threads == 0)
        return true;

    // Remember the current latch generation
    int generation = _generation;

    // Wait for the next latch generation
    return _cond.wait_for(lock, duration, [&, this]() { return generation != _generation; });
}

template <class Clock, class Duration>
inline bool Latch::TryWaitUntil(const std::chrono::time_point<Clock, Duration>& timestamp) noexcept
{
    std::unique_lock<std::mutex> lock(_mutex);

    // Check the latch threads counter value
    if (_threads == 0)
        return true;

    // Remember the current latch generation
    int generation = _generation;

    // Wait for the next latch generation
    return _cond.wait_until(lock, timestamp, [&, this]() { return generation != _generation; });
}

} // namespace CppCommon
<|endoftext|>


<commit_before>#ifndef V_SMC_CORE_RNG_HPP
#define V_SMC_CORE_RNG_HPP

#include <limits>
#include <climits>
#include <cmath>
#include <boost/cstdint.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <Random123/aes.h>
#include <Random123/ars.h>
#include <Random123/philox.h>
#include <Random123/threefry.h>

/// The Parallel RNG (based on Rand123) seed, unsigned
#ifndef V_SMC_RNG_SEED
#define V_SMC_RNG_SEED 0xdeadbeefU
#endif // V_SMC_RNG_SEED

/// The Parallel RNG (based on Rand123) type, philox or threefry
#ifndef V_SMC_RNG_TYPE
#define V_SMC_RNG_TYPE vSMC::threefry4x64_64
#endif // V_SMC_RNG_TYPE

/// Maximum of results index used by the Boost.Random eigen
#define RANDOM123_EIGEN_IDX_MAX \
    sizeof(typename cbrng_type::ctr_type) / sizeof(result_type)

/// Initializer list for random123_eigen
#define RANDOM123_EIGEN_INIT \
    index_max_(RANDOM123_EIGEN_IDX_MAX), index_(index_max_), \
    step_size_(1), ctr_index_(0), \
    ctr_max_(std::numeric_limits<ctr_value_type>::max())

namespace vSMC {

template <typename Random123Type, typename UIntType>
class random123_eigen
{
    public :

    typedef Random123Type cbrng_type;
    typedef UIntType result_type;
    typedef typename cbrng_type::key_type::value_type seed_type;
    typedef typename cbrng_type::ctr_type::value_type ctr_value_type;

    random123_eigen () : RANDOM123_EIGEN_INIT
    {
        seed();
    }

    explicit random123_eigen (seed_type k0) :
        RANDOM123_EIGEN_INIT
    {
        seed(k0);
    }

    template <typename SeedSeq>
    random123_eigen (SeedSeq &seed_seq) : RANDOM123_EIGEN_INIT
    {
        seed(seed_seq);
    }

    template <typename Iter>
    random123_eigen (Iter &first, Iter last) : RANDOM123_EIGEN_INIT
    {
        seed(first, last);
    }

    void seed ()
    {
        seed(static_cast<seed_type>(V_SMC_RNG_SEED));
    }

    void seed (seed_type k0)
    {
        ctr_.fill(0);
        key_[0] = k0;
        for (unsigned i = 1; i != key_.size(); ++i) {
            key_[i] = (key_[i-1]>>1) |
                (key_[i-1]<<(sizeof(key_[0]) * CHAR_BIT - 1));
        }
    }

    template <typename SeedSeq>
    void seed (SeedSeq &seed_seq)
    {
        ctr_.fill(0);
        key_ = cbrng_type::key_type::seed(seed_seq);
    }

    template <typename Iter>
    void seed (Iter &first, Iter last)
    {
        seed();
        for (unsigned i = 0; i != key_.size() && first != last; ++i, ++first)
            key_[i] = *first;
    }

    void step_size (unsigned size)
    {
        step_size_ = size;
    }

    static result_type min ()
    {
        return std::numeric_limits<result_type>::min();
    }

    static result_type max ()
    {
        return std::numeric_limits<result_type>::max();
    }

    result_type operator () ()
    {
        if (index_ == index_max_) {
            index_ = 0;
            advance_ctr();
            state_.c = cbrng_(ctr_, key_);
        }

        return state_.n[index_++];
    }

    void dicard (unsigned step)
    {
        index_ = (index_ + step) % index_max_;
        advance_ctr(step / index_max_);
        state_.c = cbrng_(ctr_, key_);
    }

    void advance_ctr (unsigned step = 1)
    {
        ctr_value_type inc = step * step_size_;
        if (ctr_max_ - ctr_[ctr_index_] < inc)
            ++ctr_index_;

        if (ctr_index_ == ctr_.size()) {
            ctr_.fill(0);
            ctr_index_ = 0;
        }

        ctr_[ctr_index_] += inc;
    }

    private :

    union {
        typename cbrng_type::ctr_type c;
        result_type n[RANDOM123_EIGEN_IDX_MAX];
    } state_;
    cbrng_type cbrng_;
    typename cbrng_type::ctr_type ctr_;
    typename cbrng_type::key_type key_;
    unsigned index_max_;
    unsigned index_;
    unsigned step_size_;
    unsigned ctr_index_;
    ctr_value_type ctr_max_;
};

typedef random123_eigen<r123::Philox2x32, uint32_t> philox2x32_32;
typedef random123_eigen<r123::Philox2x32, uint64_t> philox2x32_64;
typedef random123_eigen<r123::Philox4x32, uint32_t> philox4x32_32;
typedef random123_eigen<r123::Philox4x32, uint64_t> philox4x32_64;
typedef random123_eigen<r123::Philox2x64, uint32_t> philox2x64_32;
typedef random123_eigen<r123::Philox2x64, uint64_t> philox2x64_64;
typedef random123_eigen<r123::Philox4x64, uint32_t> philox4x64_32;
typedef random123_eigen<r123::Philox4x64, uint64_t> philox4x64_64;

typedef random123_eigen<r123::Threefry2x32, uint32_t> threefry2x32_32;
typedef random123_eigen<r123::Threefry2x32, uint64_t> threefry2x32_64;
typedef random123_eigen<r123::Threefry4x32, uint32_t> threefry4x32_32;
typedef random123_eigen<r123::Threefry4x32, uint64_t> threefry4x32_64;
typedef random123_eigen<r123::Threefry2x64, uint32_t> threefry2x64_32;
typedef random123_eigen<r123::Threefry2x64, uint64_t> threefry2x64_64;
typedef random123_eigen<r123::Threefry4x64, uint32_t> threefry4x64_32;
typedef random123_eigen<r123::Threefry4x64, uint64_t> threefry4x64_64;

} // namespace vSMC

#endif // V_SMC_CORE_RNG_HPP
<commit_msg>cleanup<commit_after>#ifndef V_SMC_CORE_RNG_HPP
#define V_SMC_CORE_RNG_HPP

#include <limits>
#include <climits>
#include <cmath>
#include <boost/cstdint.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <Random123/aes.h>
#include <Random123/ars.h>
#include <Random123/philox.h>
#include <Random123/threefry.h>

/// The Parallel RNG (based on Rand123) seed, unsigned
#ifndef V_SMC_RNG_SEED
#define V_SMC_RNG_SEED 0xdeadbeefU
#endif // V_SMC_RNG_SEED

/// The Parallel RNG (based on Rand123) type, philox or threefry
#ifndef V_SMC_RNG_TYPE
#define V_SMC_RNG_TYPE vSMC::threefry4x64_64
#endif // V_SMC_RNG_TYPE

/// Maximum of results index used by the Boost.Random eigen
#define RANDOM123_EIGEN_IDX_MAX \
    sizeof(typename cbrng_type::ctr_type) / sizeof(result_type)

/// Initializer list for random123_eigen
#define RANDOM123_EIGEN_INIT \
    index_max_(RANDOM123_EIGEN_IDX_MAX), index_(index_max_), \
    step_size_(1), ctr_index_(0), \
    ctr_max_(std::numeric_limits<ctr_value_type>::max())

namespace vSMC {

template <typename Random123Type, typename UIntType>
class random123_eigen
{
    public :

    typedef Random123Type cbrng_type;
    typedef UIntType result_type;
    typedef typename cbrng_type::key_type::value_type seed_type;
    typedef typename cbrng_type::ctr_type::value_type ctr_value_type;

    random123_eigen () : RANDOM123_EIGEN_INIT
    {
        ctr_.fill(0);
        seed();
    }

    explicit random123_eigen (seed_type k0) : RANDOM123_EIGEN_INIT
    {
        ctr_.fill(0);
        seed(k0);
    }

    template <typename SeedSeq>
    random123_eigen (SeedSeq &seed_seq) : RANDOM123_EIGEN_INIT
    {
        ctr_.fill(0);
        seed(seed_seq);
    }

    template <typename Iter>
    random123_eigen (Iter &first, Iter last) : RANDOM123_EIGEN_INIT
    {
        ctr_.fill(0);
        seed(first, last);
    }

    void seed ()
    {
        ctr_.fill(0);
        seed(static_cast<seed_type>(V_SMC_RNG_SEED));
    }

    void seed (seed_type k0)
    {
        key_[0] = k0;
        for (unsigned i = 1; i != key_.size(); ++i) {
            key_[i] = (key_[i-1]>>1) |
                (key_[i-1]<<(sizeof(key_[0]) * CHAR_BIT - 1));
        }
    }

    template <typename SeedSeq>
    void seed (SeedSeq &seed_seq)
    {
        key_ = cbrng_type::key_type::seed(seed_seq);
    }

    template <typename Iter>
    void seed (Iter &first, Iter last)
    {
        seed();
        for (unsigned i = 0; i != key_.size() && first != last; ++i, ++first)
            key_[i] = *first;
    }

    void step_size (unsigned size)
    {
        step_size_ = size;
    }

    static result_type min ()
    {
        return std::numeric_limits<result_type>::min();
    }

    static result_type max ()
    {
        return std::numeric_limits<result_type>::max();
    }

    result_type operator () ()
    {
        if (index_ == index_max_) {
            index_ = 0;
            advance_ctr();
            state_.c = cbrng_(ctr_, key_);
        }

        return state_.n[index_++];
    }

    void dicard (unsigned step)
    {
        index_ = (index_ + step) % index_max_;
        advance_ctr(step / index_max_);
        state_.c = cbrng_(ctr_, key_);
    }

    void advance_ctr (unsigned step = 1)
    {
        ctr_value_type inc = step * step_size_;

        if (ctr_max_ - ctr_[ctr_index_] < inc)
            ++ctr_index_;

        if (ctr_index_ == ctr_.size()) {
            ctr_.fill(0);
            ctr_index_ = 0;
        }

        ctr_[ctr_index_] += inc;
    }

    private :

    union {
        typename cbrng_type::ctr_type c;
        result_type n[RANDOM123_EIGEN_IDX_MAX];
    } state_;
    cbrng_type cbrng_;
    typename cbrng_type::ctr_type ctr_;
    typename cbrng_type::key_type key_;
    unsigned index_max_;
    unsigned index_;
    unsigned step_size_;
    unsigned ctr_index_;
    ctr_value_type ctr_max_;
};

typedef random123_eigen<r123::Philox2x32, uint32_t> philox2x32_32;
typedef random123_eigen<r123::Philox2x32, uint64_t> philox2x32_64;
typedef random123_eigen<r123::Philox4x32, uint32_t> philox4x32_32;
typedef random123_eigen<r123::Philox4x32, uint64_t> philox4x32_64;
typedef random123_eigen<r123::Philox2x64, uint32_t> philox2x64_32;
typedef random123_eigen<r123::Philox2x64, uint64_t> philox2x64_64;
typedef random123_eigen<r123::Philox4x64, uint32_t> philox4x64_32;
typedef random123_eigen<r123::Philox4x64, uint64_t> philox4x64_64;

typedef random123_eigen<r123::Threefry2x32, uint32_t> threefry2x32_32;
typedef random123_eigen<r123::Threefry2x32, uint64_t> threefry2x32_64;
typedef random123_eigen<r123::Threefry4x32, uint32_t> threefry4x32_32;
typedef random123_eigen<r123::Threefry4x32, uint64_t> threefry4x32_64;
typedef random123_eigen<r123::Threefry2x64, uint32_t> threefry2x64_32;
typedef random123_eigen<r123::Threefry2x64, uint64_t> threefry2x64_64;
typedef random123_eigen<r123::Threefry4x64, uint32_t> threefry4x64_32;
typedef random123_eigen<r123::Threefry4x64, uint64_t> threefry4x64_64;

} // namespace vSMC

#endif // V_SMC_CORE_RNG_HPP
<|endoftext|>


<commit_before>
#include <iostream>
#include <limits>
#include <random>
#include <string>
#include <type_traits>
#include <gtest/gtest.h>

using namespace std;

extern "C" {
   #include <common/string_util.h>
}

template <typename T>
inline void itoa_wrapper(T val, char *buf) { abort(); }

template <>
inline void itoa_wrapper<s32>(s32 val, char *buf) { itoa32(val, buf); }

template <>
inline void itoa_wrapper<s64>(s64 val, char *buf) { itoa64(val, buf); }

template <>
inline void itoa_wrapper<u32>(u32 val, char *buf) { uitoa32_dec(val, buf); }

template <>
inline void itoa_wrapper<u64>(u64 val, char *buf) { uitoa64_dec(val, buf); }

template <typename T>
inline void uitoa_hex_wrapper(T val, char *buf, bool fixed) { abort(); }

template<>
inline void uitoa_hex_wrapper<u32>(u32 val, char *buf, bool fixed)
{
   if (!fixed)
      uitoa32_hex(val, buf);
   else
      uitoa32_hex_fixed(val, buf);
}

template<>
inline void uitoa_hex_wrapper<u64>(u64 val, char *buf, bool fixed)
{
   if (!fixed)
      uitoa64_hex(val, buf);
   else
      uitoa64_hex_fixed(val, buf);
}

template <typename T>
inline void sprintf_hex_wrapper(T val, char *buf, bool fixed) { abort(); }

template <>
inline void sprintf_hex_wrapper<u32>(u32 val, char *buf, bool fixed)
{
   if (fixed)
      sprintf(buf, "%08x", val);
   else
      sprintf(buf, "%x", val);
}

template <>
inline void sprintf_hex_wrapper<u64>(u64 val, char *buf, bool fixed)
{
   if (fixed)
      sprintf(buf, "%016lx", val);
   else
      sprintf(buf, "%lx", val);
}

template <typename T, bool hex = false, bool fixed = false>
void check(T val)
{
   char expected[64];
   char got[64];

   memset(expected, '*', sizeof(expected));
   memset(got, '*', sizeof(got));

   if (!hex) {

      strcpy(expected, to_string(val).c_str());
      itoa_wrapper(val, got);

   } else {

      sprintf_hex_wrapper<T>(val, expected, fixed);
      uitoa_hex_wrapper<T>(val, got, fixed);

   }

   ASSERT_STREQ(got, expected);
}

template <typename T, bool hex = false, bool fixed = false>
void check_set()
{
   auto check_func = check<T, hex, fixed>;

   check_func(0);
   check_func(numeric_limits<T>::min());
   check_func(numeric_limits<T>::max());
   check_func(numeric_limits<T>::min() + 1);
   check_func(numeric_limits<T>::max() - 1);
}

TEST(itoa, u32_hex)
{
   typedef u32 T;
   auto check_func = check<T, true>;
   auto check_set_func = check_set<T, true>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, u64_hex)
{
   typedef u64 T;
   auto check_func = check<T, true>;
   auto check_set_func = check_set<T, true>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, u32_dec)
{
   typedef u32 T;
   auto check_func = check<T>;
   auto check_set_func = check_set<T>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, u64_dec)
{
   typedef u64 T;
   auto check_func = check<T>;
   auto check_set_func = check_set<T>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, u32_hex_fixed)
{
   typedef u32 T;
   auto check_func = check<T, true, true>;
   auto check_set_func = check_set<T, true, true>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, u64_hex_fixed)
{
   typedef u64 T;
   auto check_func = check<T, true, true>;
   auto check_set_func = check_set<T, true, true>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, s32_dec)
{
   typedef s32 T;
   auto check_func = check<T>;
   auto check_set_func = check_set<T>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, s64_dec)
{
   typedef s32 T;
   auto check_func = check<T>;
   auto check_set_func = check_set<T>;

   ASSERT_NO_FATAL_FAILURE({ check_set_func(); });

   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   uniform_int_distribution<T>
      dist(numeric_limits<T>::min(), numeric_limits<T>::max());

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

<commit_msg>[gtests] Final polishing of the itoa gtest<commit_after>
#include <iostream>
#include <limits>
#include <random>
#include <string>
#include <type_traits>
#include <gtest/gtest.h>

using namespace std;

extern "C" {
   #include <common/string_util.h>
}

// Wrapper defined only for s32, s64, u32, u64.
template <typename T>
inline void itoa_wrapper(T val, char *buf);

// Wrapper defined only for u32, u64.
template <typename T>
inline void uitoa_hex_wrapper(T val, char *buf, bool fixed);

// Wrapper defined only for u32, u64.
template <typename T>
inline void sprintf_hex_wrapper(T val, char *buf, bool fixed);

template <>
inline void itoa_wrapper<s32>(s32 val, char *buf) { itoa32(val, buf); }

template <>
inline void itoa_wrapper<s64>(s64 val, char *buf) { itoa64(val, buf); }

template <>
inline void itoa_wrapper<u32>(u32 val, char *buf) { uitoa32_dec(val, buf); }

template <>
inline void itoa_wrapper<u64>(u64 val, char *buf) { uitoa64_dec(val, buf); }

template<>
inline void uitoa_hex_wrapper<u32>(u32 val, char *buf, bool fixed)
{
   if (!fixed)
      uitoa32_hex(val, buf);
   else
      uitoa32_hex_fixed(val, buf);
}

template<>
inline void uitoa_hex_wrapper<u64>(u64 val, char *buf, bool fixed)
{
   if (!fixed)
      uitoa64_hex(val, buf);
   else
      uitoa64_hex_fixed(val, buf);
}

template <>
inline void sprintf_hex_wrapper<u32>(u32 val, char *buf, bool fixed)
{
   if (fixed)
      sprintf(buf, "%08x", val);
   else
      sprintf(buf, "%x", val);
}

template <>
inline void sprintf_hex_wrapper<u64>(u64 val, char *buf, bool fixed)
{
   if (fixed)
      sprintf(buf, "%016lx", val);
   else
      sprintf(buf, "%lx", val);
}

template <typename T, bool hex = false, bool fixed = false>
typename enable_if<hex, void>::type
check(T val)
{
   char expected[64];
   char got[64];

   memset(expected, '*', sizeof(expected));
   memset(got, '*', sizeof(got));

   sprintf_hex_wrapper<T>(val, expected, fixed);
   uitoa_hex_wrapper<T>(val, got, fixed);

   ASSERT_STREQ(got, expected);
}

template <typename T, bool hex = false, bool fixed = false>
typename enable_if<!hex, void>::type
check(T val)
{
   char expected[64];
   char got[64];

   memset(expected, '*', sizeof(expected));
   memset(got, '*', sizeof(got));

   strcpy(expected, to_string(val).c_str());
   itoa_wrapper(val, got);

   ASSERT_STREQ(got, expected);
}

template <typename T, bool hex = false, bool fixed = false>
void check_basic_set()
{
   auto check_func = check<T, hex, fixed>;

   ASSERT_NO_FATAL_FAILURE({
      check_func(numeric_limits<T>::lowest());
      check_func(numeric_limits<T>::min());
      check_func(numeric_limits<T>::max());
      check_func(numeric_limits<T>::min() + 1);
      check_func(numeric_limits<T>::max() - 1);
   });
}

template <typename T, bool hex = false, bool fixed = false>
void generic_itoa_test_body()
{
   random_device rdev;
   const auto seed = rdev();
   default_random_engine e(seed);

   auto check_func = check<T, hex, fixed>;
   auto check_basic_set_func = check_basic_set<T, hex, fixed>;

   uniform_int_distribution<T> dist(numeric_limits<T>::min(),
                                    numeric_limits<T>::max());

   ASSERT_NO_FATAL_FAILURE({ check_basic_set_func(); });

   for (int i = 0; i < 100000; i++)
      ASSERT_NO_FATAL_FAILURE({ check_func(dist(e)); });
}

TEST(itoa, u32_dec)
{
   auto test_func = generic_itoa_test_body<u32>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}

TEST(itoa, u64_dec)
{
   auto test_func = generic_itoa_test_body<u64>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}

TEST(itoa, s32_dec)
{
   auto test_func = generic_itoa_test_body<s32>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}

TEST(itoa, s64_dec)
{
   auto test_func = generic_itoa_test_body<s64>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}

TEST(itoa, u32_hex)
{
   auto test_func = generic_itoa_test_body<u32, true>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}

TEST(itoa, u64_hex)
{
   auto test_func = generic_itoa_test_body<u64, true>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}

TEST(itoa, u32_hex_fixed)
{
   auto test_func = generic_itoa_test_body<u32, true, true>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}

TEST(itoa, u64_hex_fixed)
{
   auto test_func = generic_itoa_test_body<u64, true, true>;
   ASSERT_NO_FATAL_FAILURE({ test_func(); });
}
<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdlib.h>
#include <string>
#include <ctime>
#include <stdint.h>
#include <fnord/inspect.h>
#include <chartsql/svalue.h>
#include <chartsql/format.h>

namespace csql {

SValue::SValue() {
  memset(&data_, 0, sizeof(data_));
  data_.type = T_NULL;
}

SValue::~SValue() {
  // FIXPAUL free string!
}

SValue::SValue(const SValue::StringType& string_value) {
  data_.type = T_STRING;
  data_.u.t_string.len = string_value.size();
  data_.u.t_string.ptr = static_cast<char *>(malloc(data_.u.t_string.len));

  if (data_.u.t_string.ptr == nullptr) {
    RAISE(kRuntimeError, "could not allocate SValue");
  }

  memcpy(
      data_.u.t_string.ptr,
      string_value.c_str(),
      data_.u.t_string.len);
}

SValue::SValue(
    char const* string_value) :
    SValue(std::string(string_value)) {}

SValue::SValue(SValue::IntegerType integer_value) {
  data_.type = T_INTEGER;
  data_.u.t_integer = integer_value;
}

SValue::SValue(SValue::FloatType float_value) {
  data_.type = T_FLOAT;
  data_.u.t_float = float_value;
}

SValue::SValue(SValue::BoolType bool_value) {
  data_.type = T_BOOL;
  data_.u.t_bool = bool_value;
}

SValue::SValue(SValue::TimeType time_value) {
  data_.type = T_TIMESTAMP;
  data_.u.t_timestamp = static_cast<uint64_t>(time_value);
}

SValue::SValue(const SValue& copy) {
  switch (copy.data_.type) {

    case T_STRING:
      data_.type = T_STRING;
      data_.u.t_string.len = copy.data_.u.t_string.len;
      data_.u.t_string.ptr = static_cast<char *>(malloc(data_.u.t_string.len));

      if (data_.u.t_string.ptr == nullptr) {
        RAISE(kRuntimeError, "could not allocate SValue");
      }

      memcpy(
          data_.u.t_string.ptr,
          copy.data_.u.t_string.ptr,
          data_.u.t_string.len);

    default:
      memcpy(&data_, &copy.data_, sizeof(data_));
      break;

  }

}

SValue& SValue::operator=(const SValue& copy) {
  // FIXPAUL free old string!

  switch (copy.data_.type) {

    case T_STRING:
      data_.type = T_STRING;
      data_.u.t_string.len = copy.data_.u.t_string.len;
      data_.u.t_string.ptr = static_cast<char *>(malloc(data_.u.t_string.len));

      if (data_.u.t_string.ptr == nullptr) {
        RAISE(kRuntimeError, "could not allocate SValue");
      }

      memcpy(
          data_.u.t_string.ptr,
          copy.data_.u.t_string.ptr,
          data_.u.t_string.len);

    default:
      memcpy(&data_, &copy.data_, sizeof(data_));
      break;

  }

  return *this;
}

bool SValue::operator==(const SValue& other) const {
  if (data_.type != other.data_.type) {
    return false;
  }

  switch (data_.type) {
    case T_STRING:
      return memcmp(
          data_.u.t_string.ptr,
          other.data_.u.t_string.ptr,
          data_.u.t_string.len) == 0;

    default:
      return memcmp(&data_, &other.data_, sizeof(data_)) == 0;

  }
}

SValue::kSValueType SValue::getType() const {
  return data_.type;
}

SValue::IntegerType SValue::getInteger() const {
  switch (data_.type) {

    case T_INTEGER:
      return data_.u.t_integer;

    case T_TIMESTAMP:
      return data_.u.t_timestamp;

    case T_STRING:
      try {
        return std::stol(getString());
      } catch (std::exception e) {
        /* fallthrough */
      }

    default:
      RAISE(
          kTypeError,
          "can't convert %s '%s' to Integer",
          SValue::getTypeName(data_.type),
          toString().c_str());

  }

  return 0;
}

SValue::FloatType SValue::getFloat() const {
  switch (data_.type) {

    case T_INTEGER:
      return data_.u.t_integer;

    case T_FLOAT:
      return data_.u.t_float;

    case T_STRING:
      try {
        return std::stod(getString());
      } catch (std::exception e) {
        /* fallthrough */
      }

    default:
      RAISE(
          kTypeError,
          "can't convert %s '%s' to Float",
          SValue::getTypeName(data_.type),
          toString().c_str());

  }

  return 0;
}

SValue::BoolType SValue::getBool() const {
  if (data_.type != T_BOOL) {
    RAISE(
       kTypeError,
        "can't convert %s '%s' to Bool",
        SValue::getTypeName(data_.type),
        toString().c_str());
  }

  return data_.u.t_bool;
}

SValue::TimeType SValue::getTimestamp() const {
  switch (getType()) {

    case T_TIMESTAMP:
      return data_.u.t_timestamp;

    default:
      RAISE(
         kTypeError,
          "can't convert %s '%s' to Timestamp",
          SValue::getTypeName(data_.type),
          toString().c_str());
      time_t ts;
      time(&ts);

  }
}

SValue::StringType SValue::getString() const {
  if (data_.type == T_STRING) {
    return std::string(data_.u.t_string.ptr, data_.u.t_string.len);
  } else {
    return toString();
  }
}

std::string SValue::makeUniqueKey(SValue* arr, size_t len) {
  std::string key;

  for (int i = 0; i < len; ++i) {
    key.append(arr[i].toString());
    key.append("\x00");
  }

  return key;
}

std::string SValue::toString() const {
  char buf[512];
  const char* str;
  size_t len;

  switch (data_.type) {

    case T_INTEGER: {
      len = snprintf(buf, sizeof(buf), "%" PRId64, getInteger());
      str = buf;
      break;
    }

    case T_TIMESTAMP: {
      return getTimestamp().toString("%Y-%m-%d %H:%M:%S");
    }

    case T_FLOAT: {
      len = snprintf(buf, sizeof(buf), "%f", getFloat());
      str = buf;
      break;
    }

    case T_BOOL: {
      static const auto true_str = "true";
      static const auto false_str = "false";
      if (getBool()) {
        str = true_str;
        len = strlen(true_str);
      } else {
        str = false_str;
        len = strlen(false_str);
      }
      break;
    }

    case T_STRING: {
      return getString();
    }

    case T_NULL: {
      static const char undef_str[] = "NULL";
      str = undef_str;
      len = sizeof(undef_str) - 1;
    }

  }

  return std::string(str, len);
}

const char* SValue::getTypeName(kSValueType type) {
  switch (type) {
    case T_STRING:
      return "String";
    case T_FLOAT:
      return "Float";
    case T_INTEGER:
      return "Integer";
    case T_BOOL:
      return "Boolean";
    case T_TIMESTAMP:
      return "Timestamp";
    case T_NULL:
      return "NULL";
  }
}

const char* SValue::getTypeName() const {
  return SValue::getTypeName(data_.type);
}

template <> SValue::BoolType SValue::getValue<SValue::BoolType>() const {
  return getBool();
}

template <> SValue::IntegerType SValue::getValue<SValue::IntegerType>() const {
  return getInteger();
}

template <> SValue::FloatType SValue::getValue<SValue::FloatType>() const {
  return getFloat();
}

template <> SValue::StringType SValue::getValue<SValue::StringType>() const {
  return toString();
}

template <> SValue::TimeType SValue::getValue<SValue::TimeType>() const {
  return getTimestamp();
}

// FIXPAUL: smarter type detection
template <> bool SValue::testType<SValue::BoolType>() const {
  return data_.type == T_BOOL;
}

template <> bool SValue::testType<SValue::TimeType>() const {
  return data_.type == T_TIMESTAMP;
}

template <> bool SValue::testType<SValue::IntegerType>() const {
  if (data_.type == T_INTEGER) {
    return true;
  }

  auto str = toString();
  const char* cur = str.c_str();
  const char* end = cur + str.size();

  if (*cur == '-') {
    ++cur;
  }

  if (cur == end) {
    return false;
  }

  for (; cur < end; ++cur) {
    if (*cur < '0' || *cur > '9') {
      return false;
    }
  }

  return true;
}

template <> bool SValue::testType<SValue::FloatType>() const {
  if (data_.type == T_FLOAT) {
    return true;
  }

  auto str = toString();
  bool dot = false;
  const char* c = str.c_str();

  if (*c == '-') {
    ++c;
  }

  for (; *c != 0; ++c) {
    if (*c >= '0' && *c <= '9') {
      continue;
    }

    if (*c == '.' || *c == ',') {
      if (dot) {
        return false;
      } else {
        dot = true;
      }
      continue;
    }

    return false;
  }

  return true;
}

template <> bool SValue::testType<std::string>() const {
  return true;
}

SValue::kSValueType SValue::testTypeWithNumericConversion() const {
  if (testType<SValue::IntegerType>()) return T_INTEGER;
  if (testType<SValue::FloatType>()) return T_FLOAT;
  return getType();
}

bool SValue::tryNumericConversion() {
  if (testType<SValue::IntegerType>()) {
    SValue::IntegerType val = getValue<SValue::IntegerType>();
    data_.type = T_INTEGER;
    data_.u.t_integer = val;
    return true;
  }

  if (testType<SValue::FloatType>()) {
    SValue::FloatType val = getValue<SValue::FloatType>();
    data_.type = T_FLOAT;
    data_.u.t_float = val;
    return true;
  }

  return false;
}

bool SValue::tryTimeConversion() {
  if (!tryNumericConversion()) {
    return false;
  }

  time_t ts = getInteger();
  data_.type = T_TIMESTAMP;
  // FIXPAUL take a smart guess if this is milli, micro, etc
  data_.u.t_timestamp = ts * 1000000llu;
  return true;
}

}

namespace fnord {

template <>
std::string inspect<csql::SValue::kSValueType>(
    const csql::SValue::kSValueType& type) {
  return csql::SValue::getTypeName(type);
}

}
<commit_msg>bring back SValue::fromToken<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdlib.h>
#include <string>
#include <ctime>
#include <stdint.h>
#include <fnord/inspect.h>
#include <chartsql/svalue.h>
#include <chartsql/format.h>
#include <chartsql/parser/token.h>

namespace csql {

SValue::SValue() {
  memset(&data_, 0, sizeof(data_));
  data_.type = T_NULL;
}

SValue::~SValue() {
  // FIXPAUL free string!
}

SValue::SValue(const SValue::StringType& string_value) {
  data_.type = T_STRING;
  data_.u.t_string.len = string_value.size();
  data_.u.t_string.ptr = static_cast<char *>(malloc(data_.u.t_string.len));

  if (data_.u.t_string.ptr == nullptr) {
    RAISE(kRuntimeError, "could not allocate SValue");
  }

  memcpy(
      data_.u.t_string.ptr,
      string_value.c_str(),
      data_.u.t_string.len);
}

SValue::SValue(
    char const* string_value) :
    SValue(std::string(string_value)) {}

SValue::SValue(SValue::IntegerType integer_value) {
  data_.type = T_INTEGER;
  data_.u.t_integer = integer_value;
}

SValue::SValue(SValue::FloatType float_value) {
  data_.type = T_FLOAT;
  data_.u.t_float = float_value;
}

SValue::SValue(SValue::BoolType bool_value) {
  data_.type = T_BOOL;
  data_.u.t_bool = bool_value;
}

SValue::SValue(SValue::TimeType time_value) {
  data_.type = T_TIMESTAMP;
  data_.u.t_timestamp = static_cast<uint64_t>(time_value);
}

SValue::SValue(const SValue& copy) {
  switch (copy.data_.type) {

    case T_STRING:
      data_.type = T_STRING;
      data_.u.t_string.len = copy.data_.u.t_string.len;
      data_.u.t_string.ptr = static_cast<char *>(malloc(data_.u.t_string.len));

      if (data_.u.t_string.ptr == nullptr) {
        RAISE(kRuntimeError, "could not allocate SValue");
      }

      memcpy(
          data_.u.t_string.ptr,
          copy.data_.u.t_string.ptr,
          data_.u.t_string.len);

    default:
      memcpy(&data_, &copy.data_, sizeof(data_));
      break;

  }

}

SValue& SValue::operator=(const SValue& copy) {
  // FIXPAUL free old string!

  switch (copy.data_.type) {

    case T_STRING:
      data_.type = T_STRING;
      data_.u.t_string.len = copy.data_.u.t_string.len;
      data_.u.t_string.ptr = static_cast<char *>(malloc(data_.u.t_string.len));

      if (data_.u.t_string.ptr == nullptr) {
        RAISE(kRuntimeError, "could not allocate SValue");
      }

      memcpy(
          data_.u.t_string.ptr,
          copy.data_.u.t_string.ptr,
          data_.u.t_string.len);

    default:
      memcpy(&data_, &copy.data_, sizeof(data_));
      break;

  }

  return *this;
}

bool SValue::operator==(const SValue& other) const {
  if (data_.type != other.data_.type) {
    return false;
  }

  switch (data_.type) {
    case T_STRING:
      return memcmp(
          data_.u.t_string.ptr,
          other.data_.u.t_string.ptr,
          data_.u.t_string.len) == 0;

    default:
      return memcmp(&data_, &other.data_, sizeof(data_)) == 0;

  }
}

SValue::kSValueType SValue::getType() const {
  return data_.type;
}

SValue::IntegerType SValue::getInteger() const {
  switch (data_.type) {

    case T_INTEGER:
      return data_.u.t_integer;

    case T_TIMESTAMP:
      return data_.u.t_timestamp;

    case T_STRING:
      try {
        return std::stol(getString());
      } catch (std::exception e) {
        /* fallthrough */
      }

    default:
      RAISE(
          kTypeError,
          "can't convert %s '%s' to Integer",
          SValue::getTypeName(data_.type),
          toString().c_str());

  }

  return 0;
}

SValue::FloatType SValue::getFloat() const {
  switch (data_.type) {

    case T_INTEGER:
      return data_.u.t_integer;

    case T_FLOAT:
      return data_.u.t_float;

    case T_STRING:
      try {
        return std::stod(getString());
      } catch (std::exception e) {
        /* fallthrough */
      }

    default:
      RAISE(
          kTypeError,
          "can't convert %s '%s' to Float",
          SValue::getTypeName(data_.type),
          toString().c_str());

  }

  return 0;
}

SValue::BoolType SValue::getBool() const {
  if (data_.type != T_BOOL) {
    RAISE(
       kTypeError,
        "can't convert %s '%s' to Bool",
        SValue::getTypeName(data_.type),
        toString().c_str());
  }

  return data_.u.t_bool;
}

SValue::TimeType SValue::getTimestamp() const {
  switch (getType()) {

    case T_TIMESTAMP:
      return data_.u.t_timestamp;

    default:
      RAISE(
         kTypeError,
          "can't convert %s '%s' to Timestamp",
          SValue::getTypeName(data_.type),
          toString().c_str());
      time_t ts;
      time(&ts);

  }
}

SValue::StringType SValue::getString() const {
  if (data_.type == T_STRING) {
    return std::string(data_.u.t_string.ptr, data_.u.t_string.len);
  } else {
    return toString();
  }
}

std::string SValue::makeUniqueKey(SValue* arr, size_t len) {
  std::string key;

  for (int i = 0; i < len; ++i) {
    key.append(arr[i].toString());
    key.append("\x00");
  }

  return key;
}

std::string SValue::toString() const {
  char buf[512];
  const char* str;
  size_t len;

  switch (data_.type) {

    case T_INTEGER: {
      len = snprintf(buf, sizeof(buf), "%" PRId64, getInteger());
      str = buf;
      break;
    }

    case T_TIMESTAMP: {
      return getTimestamp().toString("%Y-%m-%d %H:%M:%S");
    }

    case T_FLOAT: {
      len = snprintf(buf, sizeof(buf), "%f", getFloat());
      str = buf;
      break;
    }

    case T_BOOL: {
      static const auto true_str = "true";
      static const auto false_str = "false";
      if (getBool()) {
        str = true_str;
        len = strlen(true_str);
      } else {
        str = false_str;
        len = strlen(false_str);
      }
      break;
    }

    case T_STRING: {
      return getString();
    }

    case T_NULL: {
      static const char undef_str[] = "NULL";
      str = undef_str;
      len = sizeof(undef_str) - 1;
    }

  }

  return std::string(str, len);
}

const char* SValue::getTypeName(kSValueType type) {
  switch (type) {
    case T_STRING:
      return "String";
    case T_FLOAT:
      return "Float";
    case T_INTEGER:
      return "Integer";
    case T_BOOL:
      return "Boolean";
    case T_TIMESTAMP:
      return "Timestamp";
    case T_NULL:
      return "NULL";
  }
}

const char* SValue::getTypeName() const {
  return SValue::getTypeName(data_.type);
}

template <> SValue::BoolType SValue::getValue<SValue::BoolType>() const {
  return getBool();
}

template <> SValue::IntegerType SValue::getValue<SValue::IntegerType>() const {
  return getInteger();
}

template <> SValue::FloatType SValue::getValue<SValue::FloatType>() const {
  return getFloat();
}

template <> SValue::StringType SValue::getValue<SValue::StringType>() const {
  return toString();
}

template <> SValue::TimeType SValue::getValue<SValue::TimeType>() const {
  return getTimestamp();
}

// FIXPAUL: smarter type detection
template <> bool SValue::testType<SValue::BoolType>() const {
  return data_.type == T_BOOL;
}

template <> bool SValue::testType<SValue::TimeType>() const {
  return data_.type == T_TIMESTAMP;
}

template <> bool SValue::testType<SValue::IntegerType>() const {
  if (data_.type == T_INTEGER) {
    return true;
  }

  auto str = toString();
  const char* cur = str.c_str();
  const char* end = cur + str.size();

  if (*cur == '-') {
    ++cur;
  }

  if (cur == end) {
    return false;
  }

  for (; cur < end; ++cur) {
    if (*cur < '0' || *cur > '9') {
      return false;
    }
  }

  return true;
}

template <> bool SValue::testType<SValue::FloatType>() const {
  if (data_.type == T_FLOAT) {
    return true;
  }

  auto str = toString();
  bool dot = false;
  const char* c = str.c_str();

  if (*c == '-') {
    ++c;
  }

  for (; *c != 0; ++c) {
    if (*c >= '0' && *c <= '9') {
      continue;
    }

    if (*c == '.' || *c == ',') {
      if (dot) {
        return false;
      } else {
        dot = true;
      }
      continue;
    }

    return false;
  }

  return true;
}

template <> bool SValue::testType<std::string>() const {
  return true;
}

SValue::kSValueType SValue::testTypeWithNumericConversion() const {
  if (testType<SValue::IntegerType>()) return T_INTEGER;
  if (testType<SValue::FloatType>()) return T_FLOAT;
  return getType();
}

bool SValue::tryNumericConversion() {
  if (testType<SValue::IntegerType>()) {
    SValue::IntegerType val = getValue<SValue::IntegerType>();
    data_.type = T_INTEGER;
    data_.u.t_integer = val;
    return true;
  }

  if (testType<SValue::FloatType>()) {
    SValue::FloatType val = getValue<SValue::FloatType>();
    data_.type = T_FLOAT;
    data_.u.t_float = val;
    return true;
  }

  return false;
}

bool SValue::tryTimeConversion() {
  if (!tryNumericConversion()) {
    return false;
  }

  time_t ts = getInteger();
  data_.type = T_TIMESTAMP;
  // FIXPAUL take a smart guess if this is milli, micro, etc
  data_.u.t_timestamp = ts * 1000000llu;
  return true;
}

SValue* SValue::fromToken(const Token* token) {
  switch (token->getType()) {

    case Token::T_TRUE:
      return new SValue(true);

    case Token::T_FALSE:
      return new SValue(false);

    case Token::T_NUMERIC: {
      auto sval = new SValue(token->getString());
      sval->tryNumericConversion();
      return sval;
    }

    case Token::T_STRING:
      return new SValue(token->getString());

    default:
      RAISE(kRuntimeError, "can't cast Token to SValue");
      return nullptr;

  }
}

}

namespace fnord {

template <>
std::string inspect<csql::SValue::kSValueType>(
    const csql::SValue::kSValueType& type) {
  return csql::SValue::getTypeName(type);
}

}
<|endoftext|>