<commit_before>#pragma once

/**
 * \file sal/buf_ptr.hpp
 */

#include <sal/config.hpp>
#include <sal/char_array.hpp>
#include <algorithm>
#include <array>
#include <string>
#include <vector>

__sal_begin

/**
 * buf_ptr represents contiguous region of raw memory with specified size.
 * Internally it is kept as pointer pair to beginning and one byte past
 * end of region. Object of this class does not own pointed region. It is
 * application responsibility to handle lifecycle of buf_ptr and pointed
 * region.
 */
class buf_ptr
{
public:

  buf_ptr () = default;

  /**
   * Construct buf_ptr pointing to \a region with \a size.
   */
  buf_ptr (void *region, size_t size) noexcept
    : begin_(static_cast<uint8_t *>(region))
    , end_(begin_ + size)
  {}

  /**
   * Return byte pointer to beginning of region.
   */
  uint8_t *begin () const noexcept
  {
    return begin_;
  }

  /**
   * Return byte pointer to end of region.
   */
  uint8_t *end () const noexcept
  {
    return end_;
  }

  /**
   * Return raw pointer to beginning of region.
   */
  void *data () const noexcept
  {
    return begin_;
  }

  /**
   * Return raw pointer to beginning of region.
   */
  void *get () const noexcept
  {
    return begin_;
  }

  /**
   * Return size of region
   */
  size_t size () const noexcept
  {
    return end_ - begin_;
  }

  /**
   * Move beginning of pointed region by \a s bytes toward end of region.
   */
  buf_ptr &operator+= (size_t s) noexcept
  {
    begin_ += s;
    if (begin_ + s > end_)
    {
      begin_ = end_;
    }
    return *this;
  }

private:

  uint8_t *begin_{}, * const end_{};
};

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline buf_ptr operator+ (const buf_ptr &p, size_t n) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline buf_ptr operator+ (size_t n, const buf_ptr &p) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Construct buf_ptr pointing to \a region with \a size.
 */
inline buf_ptr make_buf (void *region, size_t size) noexcept
{
  return buf_ptr(region, size);
}

/**
 * Construct new buf_ptr as copy of \a ptr.
 */
inline buf_ptr make_buf (const buf_ptr &ptr) noexcept
{
  return buf_ptr(ptr.get(), ptr.size());
}

/**
 * Construct new buf_ptr as copy of \a ptr with up \a max_bytes.
 */
inline buf_ptr make_buf (const buf_ptr &ptr, size_t max_bytes) noexcept
{
  return buf_ptr(ptr.get(), (std::min)(max_bytes, ptr.size()));
}

/**
 * Construct buf_ptr using region owned by \a data
 */
template <size_t N>
inline buf_ptr make_buf (char_array_t<N> &data) noexcept
{
  // not nice, but ok: returned pointer is initialized known size area
  return buf_ptr(const_cast<char *>(data.data()), data.size());
}

/**
 * Construct buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (T (&data)[N]) noexcept
{
  return buf_ptr(data, N * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (std::array<T, N> &data) noexcept
{
  return buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data. Returned object is
 * invalidated by any vector operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Allocator>
inline buf_ptr make_buf (std::vector<T, Allocator> &data) noexcept
{
  return buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data. Returned object is
 * invalidated by any string operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Traits, typename Allocator>
inline buf_ptr make_buf (std::basic_string<T, Traits, Allocator> &data)
  noexcept
{
  return buf_ptr(&data[0], data.size() * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes
 */
template <size_t N>
inline buf_ptr make_buf (char_array_t<N> &data, size_t max_bytes) noexcept
{
  // not nice, but ok: returned pointer is initialized known size area
  return buf_ptr(const_cast<char *>(data.data()),
    (std::min)(max_bytes, data.size())
  );
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (T (&data)[N], size_t max_bytes) noexcept
{
  return buf_ptr(data, (std::min)(max_bytes, N * sizeof(T)));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (std::array<T, N> &data, size_t max_bytes) noexcept
{
  return buf_ptr(data.data(), (std::min)(max_bytes, data.size() * sizeof(T)));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Allocator>
inline buf_ptr make_buf (std::vector<T, Allocator> &data, size_t max_bytes)
  noexcept
{
  return buf_ptr(data.data(), (std::min)(max_bytes, data.size() * sizeof(T)));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Traits, typename Allocator>
inline buf_ptr make_buf (std::basic_string<T, Traits, Allocator> &data,
  size_t max_bytes) noexcept
{
  return buf_ptr(&data[0], (std::min)(max_bytes, data.size() * sizeof(T)));
}

/**
 * const_buf_ptr represents contiguous region of raw memory with specified
 * size. Internally it is kept as pointer pair to beginning and one byte past
 * end of region. Object of this class does not own pointed region. It is
 * application responsibility to handle lifecycle of buf_ptr and pointed
 * region.
 */
class const_buf_ptr
{
public:

  const_buf_ptr () = default;

  /**
   * Construct const_buf_ptr pointing to \a region with \a size.
   */
  const_buf_ptr (const void *region, size_t size) noexcept
    : begin_(static_cast<const uint8_t *>(region))
    , end_(begin_ + size)
  {}

  /**
   * Return byte pointer to beginning of region.
   */
  const uint8_t *begin () const noexcept
  {
    return begin_;
  }

  /**
   * Return byte pointer to end of region.
   */
  const uint8_t *end () const noexcept
  {
    return end_;
  }

  /**
   * Return pointer to beginning of region.
   */
  const void *data () const noexcept
  {
    return begin_;
  }

  /**
   * Return pointer to beginning of region.
   */
  const void *get () const noexcept
  {
    return begin_;
  }

  /**
   * Return size of region
   */
  size_t size () const noexcept
  {
    return end_ - begin_;
  }

  /**
   * Move beginning of pointed region by \a s bytes toward end of region.
   */
  const_buf_ptr &operator+= (size_t s) noexcept
  {
    begin_ += s;
    if (begin_ > end_)
    {
      begin_ = end_;
    }
    return *this;
  }

private:

  const uint8_t *begin_{}, * const end_{};
};

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline const_buf_ptr operator+ (const const_buf_ptr &p, size_t n) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline const_buf_ptr operator+ (size_t n, const const_buf_ptr &p) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Construct const_buf_ptr pointing to \a region with \a size.
 */
inline const_buf_ptr make_buf (const void *region, size_t size) noexcept
{
  return const_buf_ptr(region, size);
}

/**
 * Construct new const_buf_ptr as copy of \a ptr.
 */
inline const_buf_ptr make_buf (const const_buf_ptr &ptr) noexcept
{
  return const_buf_ptr(ptr.get(), ptr.size());
}

/**
 * Construct new const_buf_ptr as copy of \a ptr with up \a max_bytes.
 */
inline const_buf_ptr make_buf (const const_buf_ptr &ptr, size_t max_bytes)
  noexcept
{
  return const_buf_ptr(ptr.get(), (std::min)(max_bytes, ptr.size()));
}

/**
 * Construct const_buf_ptr using region owned by \a data
 */
template <size_t N>
inline const_buf_ptr make_buf (const char_array_t<N> &data) noexcept
{
  return const_buf_ptr(data.data(), data.size());
}

/**
 * Construct const_buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const T (&data)[N]) noexcept
{
  return const_buf_ptr(data, N * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const std::array<T, N> &data) noexcept
{
  return const_buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data. Returned object is
 * invalidated by any vector operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Allocator>
inline const_buf_ptr make_buf (const std::vector<T, Allocator> &data) noexcept
{
  return const_buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data. Returned object is
 * invalidated by any string operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Traits, typename Allocator>
inline const_buf_ptr make_buf (
  const std::basic_string<T, Traits, Allocator> &data) noexcept
{
  return const_buf_ptr(&data[0], data.size() * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <size_t N>
inline const_buf_ptr make_buf (const char_array_t<N> &data, size_t max_bytes)
  noexcept
{
  return const_buf_ptr(data.data(), (std::min)(max_bytes, data.size()));
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const T (&data)[N], size_t max_bytes) noexcept
{
  return const_buf_ptr(data, (std::min)(max_bytes, N * sizeof(T)));
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const std::array<T, N> &data, size_t max_bytes)
  noexcept
{
  return const_buf_ptr(data.data(),
    (std::min)(max_bytes, data.size() * sizeof(T))
  );
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Allocator>
inline const_buf_ptr make_buf (const std::vector<T, Allocator> &data,
  size_t max_bytes) noexcept
{
  return const_buf_ptr(data.data(),
    (std::min)(max_bytes, data.size() * sizeof(T))
  );
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Traits, typename Allocator>
inline const_buf_ptr make_buf (
  const std::basic_string<T, Traits, Allocator> &data,
  size_t max_bytes) noexcept
{
  return const_buf_ptr(&data[0],
    (std::min)(max_bytes, data.size() * sizeof(T))
  );
}

__sal_end
<commit_msg>buf_ptr: add null_buf & const_null_buf<commit_after>#pragma once

/**
 * \file sal/buf_ptr.hpp
 */

#include <sal/config.hpp>
#include <sal/char_array.hpp>
#include <algorithm>
#include <array>
#include <string>
#include <vector>

__sal_begin

/**
 * buf_ptr represents contiguous region of raw memory with specified size.
 * Internally it is kept as pointer pair to beginning and one byte past
 * end of region. Object of this class does not own pointed region. It is
 * application responsibility to handle lifecycle of buf_ptr and pointed
 * region.
 */
class buf_ptr
{
public:

  buf_ptr () = default;

  /**
   * Construct buf_ptr pointing to \a region with \a size.
   */
  buf_ptr (void *region, size_t size) noexcept
    : begin_(static_cast<uint8_t *>(region))
    , end_(begin_ + size)
  {}

  /**
   * Return byte pointer to beginning of region.
   */
  uint8_t *begin () const noexcept
  {
    return begin_;
  }

  /**
   * Return byte pointer to end of region.
   */
  uint8_t *end () const noexcept
  {
    return end_;
  }

  /**
   * Return raw pointer to beginning of region.
   */
  void *data () const noexcept
  {
    return begin_;
  }

  /**
   * Return raw pointer to beginning of region.
   */
  void *get () const noexcept
  {
    return begin_;
  }

  /**
   * Return size of region
   */
  size_t size () const noexcept
  {
    return end_ - begin_;
  }

  /**
   * Move beginning of pointed region by \a s bytes toward end of region.
   */
  buf_ptr &operator+= (size_t s) noexcept
  {
    begin_ += s;
    if (begin_ + s > end_)
    {
      begin_ = end_;
    }
    return *this;
  }

private:

  uint8_t *begin_{}, * const end_{};
};

/**
 * Nullptr buf_ptr with no size.
 */
inline const buf_ptr null_buf;

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline buf_ptr operator+ (const buf_ptr &p, size_t n) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline buf_ptr operator+ (size_t n, const buf_ptr &p) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Construct buf_ptr pointing to \a region with \a size.
 */
inline buf_ptr make_buf (void *region, size_t size) noexcept
{
  return buf_ptr(region, size);
}

/**
 * Construct new buf_ptr as copy of \a ptr.
 */
inline buf_ptr make_buf (const buf_ptr &ptr) noexcept
{
  return buf_ptr(ptr.get(), ptr.size());
}

/**
 * Construct new buf_ptr as copy of \a ptr with up \a max_bytes.
 */
inline buf_ptr make_buf (const buf_ptr &ptr, size_t max_bytes) noexcept
{
  return buf_ptr(ptr.get(), (std::min)(max_bytes, ptr.size()));
}

/**
 * Construct buf_ptr using region owned by \a data
 */
template <size_t N>
inline buf_ptr make_buf (char_array_t<N> &data) noexcept
{
  // not nice, but ok: returned pointer is initialized known size area
  return buf_ptr(const_cast<char *>(data.data()), data.size());
}

/**
 * Construct buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (T (&data)[N]) noexcept
{
  return buf_ptr(data, N * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (std::array<T, N> &data) noexcept
{
  return buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data. Returned object is
 * invalidated by any vector operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Allocator>
inline buf_ptr make_buf (std::vector<T, Allocator> &data) noexcept
{
  return buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data. Returned object is
 * invalidated by any string operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Traits, typename Allocator>
inline buf_ptr make_buf (std::basic_string<T, Traits, Allocator> &data)
  noexcept
{
  return buf_ptr(&data[0], data.size() * sizeof(T));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes
 */
template <size_t N>
inline buf_ptr make_buf (char_array_t<N> &data, size_t max_bytes) noexcept
{
  // not nice, but ok: returned pointer is initialized known size area
  return buf_ptr(const_cast<char *>(data.data()),
    (std::min)(max_bytes, data.size())
  );
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (T (&data)[N], size_t max_bytes) noexcept
{
  return buf_ptr(data, (std::min)(max_bytes, N * sizeof(T)));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline buf_ptr make_buf (std::array<T, N> &data, size_t max_bytes) noexcept
{
  return buf_ptr(data.data(), (std::min)(max_bytes, data.size() * sizeof(T)));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Allocator>
inline buf_ptr make_buf (std::vector<T, Allocator> &data, size_t max_bytes)
  noexcept
{
  return buf_ptr(data.data(), (std::min)(max_bytes, data.size() * sizeof(T)));
}

/**
 * Construct buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Traits, typename Allocator>
inline buf_ptr make_buf (std::basic_string<T, Traits, Allocator> &data,
  size_t max_bytes) noexcept
{
  return buf_ptr(&data[0], (std::min)(max_bytes, data.size() * sizeof(T)));
}

/**
 * const_buf_ptr represents contiguous region of raw memory with specified
 * size. Internally it is kept as pointer pair to beginning and one byte past
 * end of region. Object of this class does not own pointed region. It is
 * application responsibility to handle lifecycle of buf_ptr and pointed
 * region.
 */
class const_buf_ptr
{
public:

  const_buf_ptr () = default;

  /**
   * Construct const_buf_ptr pointing to \a region with \a size.
   */
  const_buf_ptr (const void *region, size_t size) noexcept
    : begin_(static_cast<const uint8_t *>(region))
    , end_(begin_ + size)
  {}

  /**
   * Return byte pointer to beginning of region.
   */
  const uint8_t *begin () const noexcept
  {
    return begin_;
  }

  /**
   * Return byte pointer to end of region.
   */
  const uint8_t *end () const noexcept
  {
    return end_;
  }

  /**
   * Return pointer to beginning of region.
   */
  const void *data () const noexcept
  {
    return begin_;
  }

  /**
   * Return pointer to beginning of region.
   */
  const void *get () const noexcept
  {
    return begin_;
  }

  /**
   * Return size of region
   */
  size_t size () const noexcept
  {
    return end_ - begin_;
  }

  /**
   * Move beginning of pointed region by \a s bytes toward end of region.
   */
  const_buf_ptr &operator+= (size_t s) noexcept
  {
    begin_ += s;
    if (begin_ > end_)
    {
      begin_ = end_;
    }
    return *this;
  }

private:

  const uint8_t *begin_{}, * const end_{};
};

/**
 * Nullptr const_buf_ptr with no size.
 */
inline const const_buf_ptr const_null_buf;

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline const_buf_ptr operator+ (const const_buf_ptr &p, size_t n) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Create and return new ptr from \a p with beginning of region moved
 * toward end by \a n bytes.
 */
inline const_buf_ptr operator+ (size_t n, const const_buf_ptr &p) noexcept
{
  auto r = p;
  r += n;
  return r;
}

/**
 * Construct const_buf_ptr pointing to \a region with \a size.
 */
inline const_buf_ptr make_buf (const void *region, size_t size) noexcept
{
  return const_buf_ptr(region, size);
}

/**
 * Construct new const_buf_ptr as copy of \a ptr.
 */
inline const_buf_ptr make_buf (const const_buf_ptr &ptr) noexcept
{
  return const_buf_ptr(ptr.get(), ptr.size());
}

/**
 * Construct new const_buf_ptr as copy of \a ptr with up \a max_bytes.
 */
inline const_buf_ptr make_buf (const const_buf_ptr &ptr, size_t max_bytes)
  noexcept
{
  return const_buf_ptr(ptr.get(), (std::min)(max_bytes, ptr.size()));
}

/**
 * Construct const_buf_ptr using region owned by \a data
 */
template <size_t N>
inline const_buf_ptr make_buf (const char_array_t<N> &data) noexcept
{
  return const_buf_ptr(data.data(), data.size());
}

/**
 * Construct const_buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const T (&data)[N]) noexcept
{
  return const_buf_ptr(data, N * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const std::array<T, N> &data) noexcept
{
  return const_buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data. Returned object is
 * invalidated by any vector operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Allocator>
inline const_buf_ptr make_buf (const std::vector<T, Allocator> &data) noexcept
{
  return const_buf_ptr(data.data(), data.size() * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data. Returned object is
 * invalidated by any string operation that invalidates all references,
 * pointers and iterators referring to the elements in the sequence.
 */
template <typename T, typename Traits, typename Allocator>
inline const_buf_ptr make_buf (
  const std::basic_string<T, Traits, Allocator> &data) noexcept
{
  return const_buf_ptr(&data[0], data.size() * sizeof(T));
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <size_t N>
inline const_buf_ptr make_buf (const char_array_t<N> &data, size_t max_bytes)
  noexcept
{
  return const_buf_ptr(data.data(), (std::min)(max_bytes, data.size()));
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const T (&data)[N], size_t max_bytes) noexcept
{
  return const_buf_ptr(data, (std::min)(max_bytes, N * sizeof(T)));
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, size_t N>
inline const_buf_ptr make_buf (const std::array<T, N> &data, size_t max_bytes)
  noexcept
{
  return const_buf_ptr(data.data(),
    (std::min)(max_bytes, data.size() * sizeof(T))
  );
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Allocator>
inline const_buf_ptr make_buf (const std::vector<T, Allocator> &data,
  size_t max_bytes) noexcept
{
  return const_buf_ptr(data.data(),
    (std::min)(max_bytes, data.size() * sizeof(T))
  );
}

/**
 * Construct const_buf_ptr using region owned by \a data but not more than
 * \a max_bytes.
 */
template <typename T, typename Traits, typename Allocator>
inline const_buf_ptr make_buf (
  const std::basic_string<T, Traits, Allocator> &data,
  size_t max_bytes) noexcept
{
  return const_buf_ptr(&data[0],
    (std::min)(max_bytes, data.size() * sizeof(T))
  );
}

__sal_end
<|endoftext|>


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

// Contact :
// Email             : solairelibrary@mail.com
// GitHub repository : https://github.com/SolaireLibrary/SolaireCPP

#include "Solaire/XML/Format.hpp"

namespace Solaire {

    static bool skipWhitespace(IStream& aStream) {
        if(aStream.end()) return true;
        char c;
        aStream >> c;
        while(std::isspace(c)) {
            if(aStream.end()) return true;
            aStream >> c;
        }
        aStream.setOffset(aStream.getOffset() - 1);
        return true;
    }

    static bool writeObject(const StringConstant<char>& aName, const GenericObject& aValue, OStream& aStream) throw();

    static bool writeArray(const StringConstant<char>& aName, const GenericArray& aValue, OStream& aStream) throw() {
        aStream << '<';
        aStream << aName;
        if(aValue.size() > 0) {
            aStream << '>';
            const auto end = aValue.end();
            for(auto i = aValue.begin(); i != end; ++i) {
                switch(i->getType()) {
                    case GenericValue::NULL_T:
                        aStream << "<solaire_array_element type=\"null\"/>";
                        break;
                    case GenericValue::CHAR_T:
                        aStream << "<solaire_array_element type=\"char\" value=\"";
                        aStream << i->getChar();
                        aStream << "\"/>";
                        break;
                    case GenericValue::BOOL_T:
                        aStream << "<solaire_array_element type=\"bool\" value=\"";
                        if(i->getBool()) {
                            aStream << "true";
                        }else {
                            aStream << "false";
                        }
                        aStream << "\"/>";
                        break;
                    case GenericValue::UNSIGNED_T:
                        aStream << "<solaire_array_element type=\"number\" value=\"";
                        aStream << i->getUnsigned();
                        aStream << "\"/>";
                        break;
                    case GenericValue::SIGNED_T:
                        aStream << "<solaire_array_element type=\"number\" value=\"";
                        aStream << i->getSigned();
                        aStream << "\"/>";
                        break;
                    case GenericValue::DOUBLE_T:
                        aStream << "<solaire_array_element type=\"number\" value=\"";
                        aStream << i->getDouble();
                        aStream << "\"/>";
                        break;
                    case GenericValue::STRING_T:
                        aStream << "<solaire_array_element type=\"string\" value=\"";
                        aStream << i->getString();
                        aStream << "\"/>";
                        break;
                    case GenericValue::ARRAY_T:
                        writeArray(CString("solaire_array_element"), i->getArray(), aStream);
                        break;
                    case GenericValue::OBJECT_T:
                        writeObject(CString("solaire_array_element"), i->getObject(), aStream);
                        break;
                    default:
                        break;
                }
            }

            aStream << '<';
            aStream << '/';
            aStream << aName;
            aStream << '>';
        }else {
            aStream << '/';
            aStream << '>';
        }
        return true;
    }

    static bool writeObject(const StringConstant<char>& aName, const GenericObject& aValue, OStream& aStream) throw() {
        if(aValue.size() == 0) {
            aStream << '<';
            aStream << aName;
            aStream << '/';
            aStream << '>';
            return true;
        }

        const auto entries = aValue.getEntries();
        const auto end = entries->end();

        aStream << '<';
        aStream << aName;

        // Write attributes
        aStream << ' ';
        for(auto i = entries->begin(); i != end; ++i) {
            switch(i->second.getType()) {
            case GenericValue::NULL_T:
                aStream << i->first;
                aStream << "=\"null\" ";
                break;
            case GenericValue::CHAR_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getChar();
                aStream << "\" ";
                break;
            case GenericValue::BOOL_T:
                aStream << i->first;
                if(i->second.getBool()) {
                    aStream << "=\"true\" ";
                }else {
                    aStream << "=\"false\" ";
                }
                break;
            case GenericValue::UNSIGNED_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getUnsigned();
                aStream << "\" ";
                break;
            case GenericValue::SIGNED_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getSigned();
                aStream << "\" ";
                break;
            case GenericValue::DOUBLE_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getDouble();
                aStream << "\" ";
                break;
            case GenericValue::STRING_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getString();
                aStream << "\" ";
                break;
            default:
                break;
            }
        }

        aStream << '>';

        // Write elements
        for(auto i = entries->begin(); i != end; ++i) {
            switch(i->second.getType()) {
            case GenericValue::ARRAY_T:
                writeArray(i->first, i->second.getArray(), aStream);
                break;
            case GenericValue::OBJECT_T:
                writeObject(i->first, i->second.getObject(), aStream);
                break;
            default:
                break;
            }
        }

        aStream << '<';
        aStream << '/';
        aStream << aName;
        aStream << '>';
        return true;
    }

    // JsonFormat

    SOLAIRE_EXPORT_CALL XmlFormat::~XmlFormat() {

    }

    GenericValue SOLAIRE_EXPORT_CALL XmlFormat::readValue(IStream& aStream) const throw() {
        try{
            //! \todo Implement XML read
            throw std::runtime_error("Not implemented");
        }catch(std::exception& e) {
            std::cerr << e.what() << std::endl;
            return GenericValue();
        }
    }

    bool SOLAIRE_EXPORT_CALL XmlFormat::writeValue(const GenericValue& aValue, OStream& aStream) const throw() {

        try{
            switch(aValue.getType()) {
            case GenericValue::ARRAY_T:
                return writeArray(CString("array"), aValue.getArray(), aStream);
            case GenericValue::OBJECT_T:
                return writeObject(CString("object"), aValue.getObject(), aStream);
            default:
                return false;
            }
        }catch(std::exception& e) {
            std::cerr << e.what() << std::endl;
            return false;
        }
    }

    Attribute XmlFormat::readAttribute(IStream& aStream) const throw() {
        if(! skipWhitespace(aStream)) return Attribute();
        CString name;
        char c;
        if(aStream.end()) return Attribute();
        aStream >> c;
        while(c != '=') {
            if(aStream.end()) return Attribute();
            name += c;
            aStream >> c;
        }
        if(aStream.end()) return Attribute();
        aStream >> c;
        if(c != '"') return Attribute();
        CString value;
        if(aStream.end()) return Attribute();
        aStream >> c;
        while(c != '"') {
            if(aStream.end()) return Attribute();
            name += c;
            aStream >> c;
        }
        return Attribute(name, value);
    }

    bool XmlFormat::writeAttribute(const Attribute& aAttribute, OStream& aStream) const throw() {
        aStream << aAttribute.getName() << "=\"" << aAttribute.getValue() << '"';
        return true;
    }

    Element XmlFormat::readElement(IStream& aStream) const throw() {
        if(! skipWhitespace(aStream)) return Element();
        char c;
        Element element;
        String<char>& name = element.getName();
        String<char>& body = element.getBody();
        List<Attribute>& attributes = element.getAttributes();
        List<Element>& elements = element.getElements();

        // Start tag
        {
            // Open tag
            if(aStream.end()) return Element();
            aStream >> c;
            if(c != '<')  return Element();

            // Read name
            if(aStream.end()) return Element();
            aStream >> c;

            while(! (std::isspace(c) || c == '/' || c == '>')) {
                name += c;
                if(aStream.end()) return Element();
                aStream >> c;
            }

            // Close tag
            bool endTag = true;
            while(endTag) {
                while(std::isspace(c)) {
                    if(aStream.end()) return Element();
                    aStream >> c;
                }
                if(c == '/') {
                    if(aStream.end()) return Element();
                    aStream >> c;
                    if(c != '>')  return Element();
                    return element;
                }else if(c == '>') {
                    endTag = false;
                }else{
                    aStream.setOffset(aStream.getOffset() - 1);
                    // Read attributes
                    attributes.pushBack(readAttribute(aStream));
                    c = aStream.peek<char>();
                }
            }
        }

        // Body
        {
            bool endBody = true;
            while(endBody){
                while(std::isspace(c)) {
                    if(aStream.end()) return Element();
                    aStream >> c;
                }

                if(c == '<'){
                    if(aStream.end()) return Element();
                    aStream >> c;
                    if(c == '/'){
                        endBody = false;
                        aStream.setOffset(aStream.getOffset() - 2);
                    }else {
                        // Read Element
                        aStream.setOffset(aStream.getOffset() - 2);
                        elements.pushBack(readElement(aStream));
                        c = aStream.peek<char>();
                    }
                }else{
                    // Read body
                    body += c;
                    if(aStream.end()) return Element();
                    aStream >> c;
                }
            }

        }

        // End tag
        {

            // Open tag
            while(std::isspace(c)) {
                if(aStream.end()) return Element();
                aStream >> c;
            }
            if(aStream.end()) return Element();
            aStream >> c;
            if(c != '<') return Element();

            if(aStream.end()) return Element();
            aStream >> c;
            if(c != '/') return Element();

            // Read name
            while(std::isspace(c)) {
                if(aStream.end()) return Element();
                aStream >> c;
            }

            CString endName;
            while(! (std::isspace(c) || c == '>')) {
                endName += c;
                if(aStream.end()) return Element();
                aStream >> c;
            }

            if(name != endName) return Element();

            // Close Tag
            while(c != '>') {
                if(aStream.end()) return Element();
                aStream >> c;
            }
        }

        return element;
    }

    bool XmlFormat::writeElement(const Element& aElement, OStream& aStream) const throw() {
        aStream << '<' << aElement.getName();

        const StaticContainer<const Attribute>& attributes = aElement.getAttributes();
        if(attributes.size() > 0) {
            aStream << ' ';
            for(const Attribute& i : attributes) {
                writeAttribute(i, aStream);
                aStream << ' ';
            }
        }

        const int32_t bodySize = aElement.getBody().size();
        const int32_t elementCount = aElement.getElements().size();
        if(bodySize + elementCount == 0) {
            aStream << "/>";
        }else {
            aStream << '>';

            if(bodySize != 0) {
                if(elementCount != 0) return false;
                const StaticContainer<const Element>& elements = aElement.getElements();
                for(const Element& i : elements) {
                    writeElement(i, aStream);
                }
            }else {
                aStream << aElement.getBody();
            }

            aStream << "</";
            aStream << aElement.getName();
            aStream << '>';
        }
        return true;
    }

}
<commit_msg>Added partial logic for convertion form Xml element to GenericValue<commit_after>//Copyright 2015 Adam Smith
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

// Contact :
// Email             : solairelibrary@mail.com
// GitHub repository : https://github.com/SolaireLibrary/SolaireCPP

#include "Solaire/XML/Format.hpp"

namespace Solaire {

    static bool skipWhitespace(IStream& aStream) {
        if(aStream.end()) return true;
        char c;
        aStream >> c;
        while(std::isspace(c)) {
            if(aStream.end()) return true;
            aStream >> c;
        }
        aStream.setOffset(aStream.getOffset() - 1);
        return true;
    }

    static bool writeObject(const StringConstant<char>& aName, const GenericObject& aValue, OStream& aStream) throw();

    static bool writeArray(const StringConstant<char>& aName, const GenericArray& aValue, OStream& aStream) throw() {
        aStream << '<';
        aStream << aName;
        if(aValue.size() > 0) {
            aStream << '>';
            const auto end = aValue.end();
            for(auto i = aValue.begin(); i != end; ++i) {
                switch(i->getType()) {
                    case GenericValue::NULL_T:
                        aStream << "<solaire_array_element type=\"null\"/>";
                        break;
                    case GenericValue::CHAR_T:
                        aStream << "<solaire_array_element type=\"char\" value=\"";
                        aStream << i->getChar();
                        aStream << "\"/>";
                        break;
                    case GenericValue::BOOL_T:
                        aStream << "<solaire_array_element type=\"bool\" value=\"";
                        if(i->getBool()) {
                            aStream << "true";
                        }else {
                            aStream << "false";
                        }
                        aStream << "\"/>";
                        break;
                    case GenericValue::UNSIGNED_T:
                        aStream << "<solaire_array_element type=\"number\" value=\"";
                        aStream << i->getUnsigned();
                        aStream << "\"/>";
                        break;
                    case GenericValue::SIGNED_T:
                        aStream << "<solaire_array_element type=\"number\" value=\"";
                        aStream << i->getSigned();
                        aStream << "\"/>";
                        break;
                    case GenericValue::DOUBLE_T:
                        aStream << "<solaire_array_element type=\"number\" value=\"";
                        aStream << i->getDouble();
                        aStream << "\"/>";
                        break;
                    case GenericValue::STRING_T:
                        aStream << "<solaire_array_element type=\"string\" value=\"";
                        aStream << i->getString();
                        aStream << "\"/>";
                        break;
                    case GenericValue::ARRAY_T:
                        writeArray(CString("solaire_array_element"), i->getArray(), aStream);
                        break;
                    case GenericValue::OBJECT_T:
                        writeObject(CString("solaire_array_element"), i->getObject(), aStream);
                        break;
                    default:
                        break;
                }
            }

            aStream << '<';
            aStream << '/';
            aStream << aName;
            aStream << '>';
        }else {
            aStream << '/';
            aStream << '>';
        }
        return true;
    }

    static bool writeObject(const StringConstant<char>& aName, const GenericObject& aValue, OStream& aStream) throw() {
        if(aValue.size() == 0) {
            aStream << '<';
            aStream << aName;
            aStream << '/';
            aStream << '>';
            return true;
        }

        const auto entries = aValue.getEntries();
        const auto end = entries->end();

        aStream << '<';
        aStream << aName;

        // Write attributes
        aStream << ' ';
        for(auto i = entries->begin(); i != end; ++i) {
            switch(i->second.getType()) {
            case GenericValue::NULL_T:
                aStream << i->first;
                aStream << "=\"null\" ";
                break;
            case GenericValue::CHAR_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getChar();
                aStream << "\" ";
                break;
            case GenericValue::BOOL_T:
                aStream << i->first;
                if(i->second.getBool()) {
                    aStream << "=\"true\" ";
                }else {
                    aStream << "=\"false\" ";
                }
                break;
            case GenericValue::UNSIGNED_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getUnsigned();
                aStream << "\" ";
                break;
            case GenericValue::SIGNED_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getSigned();
                aStream << "\" ";
                break;
            case GenericValue::DOUBLE_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getDouble();
                aStream << "\" ";
                break;
            case GenericValue::STRING_T:
                aStream << i->first;
                aStream << "=\"";
                aStream << i->second.getString();
                aStream << "\" ";
                break;
            default:
                break;
            }
        }

        aStream << '>';

        // Write elements
        for(auto i = entries->begin(); i != end; ++i) {
            switch(i->second.getType()) {
            case GenericValue::ARRAY_T:
                writeArray(i->first, i->second.getArray(), aStream);
                break;
            case GenericValue::OBJECT_T:
                writeObject(i->first, i->second.getObject(), aStream);
                break;
            default:
                break;
            }
        }

        aStream << '<';
        aStream << '/';
        aStream << aName;
        aStream << '>';
        return true;
    }

    static GenericValue elementToGenericValue(const Element& aElement) throw() {
        const String<char>& body = aElement.getBody();
        const List<const Attribute>& attributes = aElement.getAttributes();
        const List<const Element>& elements = aElement.getElements();
        const int32_t bodySize = body.size();
        const int32_t attributeCount = attributes.size();
        const int32_t elementCount = elements.size();

        if(bodySize + attributeCount + elementCount == 0) return GenericValue();
        if(attributeCount + elementCount > 0) {
            // Parse object
        }else if(attributeCount + elementCount > 0) {
            if(bodySize > 0) return GenericValue();
            // Check if array
            // Parse array
            // Check if object
            // Parse object
            return GenericValue();
        }else{
            // Parse body value
            GenericValue();
        }

        //! \todo convert Element to GenericValue
        return GenericValue();
    }

    // JsonFormat

    SOLAIRE_EXPORT_CALL XmlFormat::~XmlFormat() {

    }

    GenericValue SOLAIRE_EXPORT_CALL XmlFormat::readValue(IStream& aStream) const throw() {
        return elementToGenericValue(readElement(aStream));
    }

    bool SOLAIRE_EXPORT_CALL XmlFormat::writeValue(const GenericValue& aValue, OStream& aStream) const throw() {

        try{
            switch(aValue.getType()) {
            case GenericValue::ARRAY_T:
                return writeArray(CString("array"), aValue.getArray(), aStream);
            case GenericValue::OBJECT_T:
                return writeObject(CString("object"), aValue.getObject(), aStream);
            default:
                return false;
            }
        }catch(std::exception& e) {
            std::cerr << e.what() << std::endl;
            return false;
        }
    }

    Attribute XmlFormat::readAttribute(IStream& aStream) const throw() {
        if(! skipWhitespace(aStream)) return Attribute();
        CString name;
        char c;
        if(aStream.end()) return Attribute();
        aStream >> c;
        while(c != '=') {
            if(aStream.end()) return Attribute();
            name += c;
            aStream >> c;
        }
        if(aStream.end()) return Attribute();
        aStream >> c;
        if(c != '"') return Attribute();
        CString value;
        if(aStream.end()) return Attribute();
        aStream >> c;
        while(c != '"') {
            if(aStream.end()) return Attribute();
            name += c;
            aStream >> c;
        }
        return Attribute(name, value);
    }

    bool XmlFormat::writeAttribute(const Attribute& aAttribute, OStream& aStream) const throw() {
        aStream << aAttribute.getName() << "=\"" << aAttribute.getValue() << '"';
        return true;
    }

    Element XmlFormat::readElement(IStream& aStream) const throw() {
        if(! skipWhitespace(aStream)) return Element();
        char c;
        Element element;
        String<char>& name = element.getName();
        String<char>& body = element.getBody();
        List<Attribute>& attributes = element.getAttributes();
        List<Element>& elements = element.getElements();

        // Start tag
        {
            // Open tag
            if(aStream.end()) return Element();
            aStream >> c;
            if(c != '<')  return Element();

            // Read name
            if(aStream.end()) return Element();
            aStream >> c;

            while(! (std::isspace(c) || c == '/' || c == '>')) {
                name += c;
                if(aStream.end()) return Element();
                aStream >> c;
            }

            // Close tag
            bool endTag = true;
            while(endTag) {
                while(std::isspace(c)) {
                    if(aStream.end()) return Element();
                    aStream >> c;
                }
                if(c == '/') {
                    if(aStream.end()) return Element();
                    aStream >> c;
                    if(c != '>')  return Element();
                    return element;
                }else if(c == '>') {
                    endTag = false;
                }else{
                    aStream.setOffset(aStream.getOffset() - 1);
                    // Read attributes
                    attributes.pushBack(readAttribute(aStream));
                    c = aStream.peek<char>();
                }
            }
        }

        // Body
        {
            bool endBody = true;
            while(endBody){
                while(std::isspace(c)) {
                    if(aStream.end()) return Element();
                    aStream >> c;
                }

                if(c == '<'){
                    if(aStream.end()) return Element();
                    aStream >> c;
                    if(c == '/'){
                        endBody = false;
                        aStream.setOffset(aStream.getOffset() - 2);
                    }else {
                        // Read Element
                        aStream.setOffset(aStream.getOffset() - 2);
                        elements.pushBack(readElement(aStream));
                        c = aStream.peek<char>();
                    }
                }else{
                    // Read body
                    body += c;
                    if(aStream.end()) return Element();
                    aStream >> c;
                }
            }

        }

        // End tag
        {

            // Open tag
            while(std::isspace(c)) {
                if(aStream.end()) return Element();
                aStream >> c;
            }
            if(aStream.end()) return Element();
            aStream >> c;
            if(c != '<') return Element();

            if(aStream.end()) return Element();
            aStream >> c;
            if(c != '/') return Element();

            // Read name
            while(std::isspace(c)) {
                if(aStream.end()) return Element();
                aStream >> c;
            }

            CString endName;
            while(! (std::isspace(c) || c == '>')) {
                endName += c;
                if(aStream.end()) return Element();
                aStream >> c;
            }

            if(name != endName) return Element();

            // Close Tag
            while(c != '>') {
                if(aStream.end()) return Element();
                aStream >> c;
            }
        }

        return element;
    }

    bool XmlFormat::writeElement(const Element& aElement, OStream& aStream) const throw() {
        aStream << '<' << aElement.getName();

        const StaticContainer<const Attribute>& attributes = aElement.getAttributes();
        if(attributes.size() > 0) {
            aStream << ' ';
            for(const Attribute& i : attributes) {
                writeAttribute(i, aStream);
                aStream << ' ';
            }
        }

        const int32_t bodySize = aElement.getBody().size();
        const int32_t elementCount = aElement.getElements().size();
        if(bodySize + elementCount == 0) {
            aStream << "/>";
        }else {
            aStream << '>';

            if(bodySize != 0) {
                if(elementCount != 0) return false;
                const StaticContainer<const Element>& elements = aElement.getElements();
                for(const Element& i : elements) {
                    writeElement(i, aStream);
                }
            }else {
                aStream << aElement.getBody();
            }

            aStream << "</";
            aStream << aElement.getName();
            aStream << '>';
        }
        return true;
    }

}
<|endoftext|>


<commit_before>#include "common.h"
#include "Freefall.h"
#include <glm/gtc/random.hpp>
#include "Polar.h"
#include "JobManager.h"
#include "EventManager.h"
#include "AssetManager.h"
#include "InputManager.h"
#include "Integrator.h"
#include "Tweener.h"
#include "AudioManager.h"
#include "GL32Renderer.h"
#include "World.h"
#include "MenuSystem.h"
#include "TitlePlayerController.h"
#include "HumanPlayerController.h"
#include "BoundingComponent.h"
#include "Text.h"

void Freefall::Run(const std::vector<std::string> &args) {
	const double secsPerBeat = 1.2631578947368421;
	Polar engine;
	IDType playerID;

	srand((unsigned int)time(0));
	std::mt19937_64 rng(time(0));

	engine.AddState("root", [] (Polar *engine, EngineState &st) {
		st.transitions.emplace("forward", Transition{Push("world")});

		//st.AddSystem<JobManager>();
		st.AddSystem<EventManager>();
		st.AddSystem<InputManager>();
		st.AddSystem<AssetManager>();
		st.AddSystem<Integrator>();
		st.AddSystem<Tweener<float>>();
		st.AddSystem<AudioManager>();
		st.AddSystemAs<Renderer, GL32Renderer, const boost::container::vector<std::string> &>({ "perlin" });

		auto assetM = engine->GetSystem<AssetManager>().lock();
		assetM->Get<AudioAsset>("nexus");
		assetM->Get<AudioAsset>("laser");
		assetM->Get<AudioAsset>("beep1");
		assetM->Get<AudioAsset>("menu1");
		assetM->Get<AudioAsset>("30");
		assetM->Get<AudioAsset>("60");
		assetM->Get<AudioAsset>("1");
		assetM->Get<AudioAsset>("2");
		assetM->Get<AudioAsset>("3");
		assetM->Get<AudioAsset>("4");
		assetM->Get<AudioAsset>("5");
		assetM->Get<AudioAsset>("6");
		assetM->Get<AudioAsset>("7");
		assetM->Get<AudioAsset>("8");
		assetM->Get<AudioAsset>("9");
		assetM->Get<AudioAsset>("seconds");
		assetM->Get<AudioAsset>("hundred");
		assetM->Get<AudioAsset>("fifty");
		assetM->Get<AudioAsset>("freefall");

		engine->transition = "forward";
	});

	engine.AddState("world", [&rng, &playerID] (Polar *engine, EngineState &st) {
		st.transitions.emplace("forward", Transition{Push("title")});

		st.AddSystem<World>();

		st.dtors.emplace_back(engine->AddObject(&playerID));

		Point3 seed = glm::ballRand(Decimal(1000.0));
		engine->AddComponent<PositionComponent>(playerID, seed);
		engine->AddComponent<OrientationComponent>(playerID);

		auto renderer = engine->GetSystem<Renderer>().lock();
		renderer->SetUniform("u_baseThreshold", Decimal(   0.7));
		renderer->SetUniform("u_beatTicks",     Decimal(1000.0));
		renderer->SetUniform("u_beatPower",     Decimal(   4.0));
		renderer->SetUniform("u_beatStrength",  Decimal(   0.005));
		renderer->SetUniform("u_waveTicks",     Decimal(2345.0));
		renderer->SetUniform("u_wavePower",     Decimal(   8.0));
		renderer->SetUniform("u_waveStrength",  Decimal(   0.02));
		renderer->SetUniform("u_worldScale", Point3(20.0));

		engine->transition = "forward";
	});

	engine.AddState("title", [&playerID] (Polar *engine, EngineState &st) {
		st.transitions.emplace("forward", Transition{ Pop(), Push("playing") });
		st.transitions.emplace("back", Transition{ QuitAction() });

		st.AddSystem<TitlePlayerController>(playerID);

		auto assetM = engine->GetSystem<AssetManager>().lock();
		auto inputM = engine->GetSystem<InputManager>().lock();
		auto tweener = engine->GetSystem<Tweener<float>>().lock();
		auto renderer = engine->GetSystem<Renderer>().lock();
		auto audioM = engine->GetSystem<AudioManager>().lock();

		Menu menu = {
			MenuItem("Solo Play", [engine] (Decimal) {
				engine->transition = "forward";
				return false;
			}),
			MenuItem("Options", {
				MenuItem("Graphics", {
					MenuItem("Base Detail", MenuControl::Slider<Decimal>(6, 30, renderer->GetUniformDecimal("u_baseDetail", 10)), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_baseDetail", x);
						return true;
					}),
					//MenuItem("Far Detail", MenuControl::Slider<Decimal>(), [] (Decimal) { return true; }),
					//MenuItem("Far Limiter", MenuControl::Slider<Decimal>(), [] (Decimal) { return true; }),
					//MenuItem("Precision", MenuControl::Selection({"Float", "Double"}), [] (Decimal) { return true; }),
					MenuItem("Pixel Factor", MenuControl::Slider<Decimal>(0, 20, renderer->GetUniformDecimal("u_pixelFactor", 0)), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_pixelFactor", x);
						return true;
					}),
					MenuItem("Voxel Factor", MenuControl::Slider<Decimal>(0, 20, renderer->GetUniformDecimal("u_voxelFactor", 0)), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_voxelFactor", x);
						return true;
					}),
					MenuItem("Show FPS", MenuControl::Checkbox(renderer->showFPS), [engine] (Decimal state) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->showFPS = state;
						return true;
					}),
				}),
				MenuItem("Audio", {
					MenuItem("Mute", MenuControl::Checkbox(audioM->muted), [engine] (Decimal state) {
						auto audioM = engine->GetSystem<AudioManager>().lock();
						audioM->muted = state;
						return true;
					}),
				}),
				//MenuItem("Controls", [] (Decimal) { return true; }),
				MenuItem("World", {
					MenuItem("u_baseThreshold", MenuControl::Slider<Decimal>(0, 1, renderer->GetUniformDecimal("u_baseThreshold"), 0.05), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_baseThreshold", x);
						return true;
					}),
					MenuItem("u_beatTicks", MenuControl::Slider<Decimal>(50, 10000, renderer->GetUniformDecimal("u_beatTicks"), 50), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_beatTicks", x);
						return true;
					}),
					MenuItem("u_beatPower", MenuControl::Slider<Decimal>(1, 16, renderer->GetUniformDecimal("u_beatPower")), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_beatPower", x);
						return true;
					}),
					MenuItem("u_beatStrength", MenuControl::Slider<Decimal>(-1, 1, renderer->GetUniformDecimal("u_beatStrength"), 0.002), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_beatStrength", x);
						return true;
					}),
					MenuItem("u_waveTicks", MenuControl::Slider<Decimal>(50, 10000, renderer->GetUniformDecimal("u_waveTicks"), 50), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_waveTicks", x);
						return true;
					}),
					MenuItem("u_wavePower", MenuControl::Slider<Decimal>(1, 16, renderer->GetUniformDecimal("u_wavePower")), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_wavePower", x);
						return true;
					}),
					MenuItem("u_waveStrength", MenuControl::Slider<Decimal>(-1, 1, renderer->GetUniformDecimal("u_waveStrength"), 0.002), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_waveStrength", x);
						return true;
					}),
					MenuItem("u_worldScale.x", MenuControl::Slider<Decimal>(1, 100, renderer->GetUniformPoint3("u_worldScale").x, 0.5), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						auto p = renderer->GetUniformPoint3("u_worldScale");
						p.x = x;
						renderer->SetUniform("u_worldScale", p);
						return true;
					}),
					MenuItem("u_worldScale.y", MenuControl::Slider<Decimal>(1, 100, renderer->GetUniformPoint3("u_worldScale").y, 0.5), [engine] (Decimal y) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						auto p = renderer->GetUniformPoint3("u_worldScale");
						p.y = y;
						renderer->SetUniform("u_worldScale", p);
						return true;
					}),
					MenuItem("u_worldScale.z", MenuControl::Slider<Decimal>(1, 100, renderer->GetUniformPoint3("u_worldScale").z, 0.5), [engine] (Decimal z) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						auto p = renderer->GetUniformPoint3("u_worldScale");
						p.z = z;
						renderer->SetUniform("u_worldScale", p);
						return true;
					}),
				}),
			}),
			MenuItem("Quit Game", [engine] (Decimal) {
				engine->Quit();
				return false;
			}),
		};
		st.AddSystem<MenuSystem>(menu);

		IDType laserID;
		st.dtors.emplace_back(engine->AddObject(&laserID));
		engine->AddComponent<AudioSource>(laserID, assetM->Get<AudioAsset>("laser"), true);

		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 1.0, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.r = x;
			renderer->SetUniform("u_color", color);
		}, 5.0 * 4 - 1.0, renderer->GetUniformPoint3("u_color").r));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.g = x;
			renderer->SetUniform("u_color", color);
		}, 5.0 * 2 - 1.0, renderer->GetUniformPoint3("u_color").g));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.b = x;
			renderer->SetUniform("u_color", color);
		}, 5.0 - 1.0, renderer->GetUniformPoint3("u_color").b));
	});

	engine.AddState("playing", [secsPerBeat, &playerID] (Polar *engine, EngineState &st) {
		st.transitions.emplace("back", Transition{Pop(), Pop(), Push("world")});

		st.AddSystem<HumanPlayerController>(playerID);

		auto assetM = engine->GetSystem<AssetManager>().lock();
		auto inputM = engine->GetSystem<InputManager>().lock();
		auto tweener = engine->GetSystem<Tweener<float>>().lock();
		auto renderer = engine->GetSystem<Renderer>().lock();

		st.dtors.emplace_back(inputM->On(Key::Escape,         [engine] (Key) { engine->transition = "back"; }));
		st.dtors.emplace_back(inputM->On(Key::ControllerBack, [engine] (Key) { engine->transition = "back"; }));

		IDType beepID;
		st.dtors.emplace_back(engine->AddObject(&beepID));
		engine->AddComponent<AudioSource>(beepID, assetM->Get<AudioAsset>("begin"));

		IDType musicID;
		st.dtors.emplace_back(engine->AddObject(&musicID));
		engine->AddComponent<AudioSource>(musicID, assetM->Get<AudioAsset>("nexus"), LoopIn{3565397});

		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.r = x;
			renderer->SetUniform("u_color", color);
		}, secsPerBeat * 4 - 0.5, renderer->GetUniformPoint3("u_color").r));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.g = x;
			renderer->SetUniform("u_color", color);
		}, secsPerBeat * 2 - 0.5, renderer->GetUniformPoint3("u_color").g));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.b = x;
			renderer->SetUniform("u_color", color);
		}, secsPerBeat - 0.5, renderer->GetUniformPoint3("u_color").b));
	});

	engine.Run("root");
}
<commit_msg>Increase max base detail to 40<commit_after>#include "common.h"
#include "Freefall.h"
#include <glm/gtc/random.hpp>
#include "Polar.h"
#include "JobManager.h"
#include "EventManager.h"
#include "AssetManager.h"
#include "InputManager.h"
#include "Integrator.h"
#include "Tweener.h"
#include "AudioManager.h"
#include "GL32Renderer.h"
#include "World.h"
#include "MenuSystem.h"
#include "TitlePlayerController.h"
#include "HumanPlayerController.h"
#include "BoundingComponent.h"
#include "Text.h"

void Freefall::Run(const std::vector<std::string> &args) {
	const double secsPerBeat = 1.2631578947368421;
	Polar engine;
	IDType playerID;

	srand((unsigned int)time(0));
	std::mt19937_64 rng(time(0));

	engine.AddState("root", [] (Polar *engine, EngineState &st) {
		st.transitions.emplace("forward", Transition{Push("world")});

		//st.AddSystem<JobManager>();
		st.AddSystem<EventManager>();
		st.AddSystem<InputManager>();
		st.AddSystem<AssetManager>();
		st.AddSystem<Integrator>();
		st.AddSystem<Tweener<float>>();
		st.AddSystem<AudioManager>();
		st.AddSystemAs<Renderer, GL32Renderer, const boost::container::vector<std::string> &>({ "perlin" });

		auto assetM = engine->GetSystem<AssetManager>().lock();
		assetM->Get<AudioAsset>("nexus");
		assetM->Get<AudioAsset>("laser");
		assetM->Get<AudioAsset>("beep1");
		assetM->Get<AudioAsset>("menu1");
		assetM->Get<AudioAsset>("30");
		assetM->Get<AudioAsset>("60");
		assetM->Get<AudioAsset>("1");
		assetM->Get<AudioAsset>("2");
		assetM->Get<AudioAsset>("3");
		assetM->Get<AudioAsset>("4");
		assetM->Get<AudioAsset>("5");
		assetM->Get<AudioAsset>("6");
		assetM->Get<AudioAsset>("7");
		assetM->Get<AudioAsset>("8");
		assetM->Get<AudioAsset>("9");
		assetM->Get<AudioAsset>("seconds");
		assetM->Get<AudioAsset>("hundred");
		assetM->Get<AudioAsset>("fifty");
		assetM->Get<AudioAsset>("freefall");

		engine->transition = "forward";
	});

	engine.AddState("world", [&rng, &playerID] (Polar *engine, EngineState &st) {
		st.transitions.emplace("forward", Transition{Push("title")});

		st.AddSystem<World>();

		st.dtors.emplace_back(engine->AddObject(&playerID));

		Point3 seed = glm::ballRand(Decimal(1000.0));
		engine->AddComponent<PositionComponent>(playerID, seed);
		engine->AddComponent<OrientationComponent>(playerID);

		auto renderer = engine->GetSystem<Renderer>().lock();
		renderer->SetUniform("u_baseThreshold", Decimal(   0.7));
		renderer->SetUniform("u_beatTicks",     Decimal(1000.0));
		renderer->SetUniform("u_beatPower",     Decimal(   4.0));
		renderer->SetUniform("u_beatStrength",  Decimal(   0.005));
		renderer->SetUniform("u_waveTicks",     Decimal(2345.0));
		renderer->SetUniform("u_wavePower",     Decimal(   8.0));
		renderer->SetUniform("u_waveStrength",  Decimal(   0.02));
		renderer->SetUniform("u_worldScale", Point3(20.0));

		engine->transition = "forward";
	});

	engine.AddState("title", [&playerID] (Polar *engine, EngineState &st) {
		st.transitions.emplace("forward", Transition{ Pop(), Push("playing") });
		st.transitions.emplace("back", Transition{ QuitAction() });

		st.AddSystem<TitlePlayerController>(playerID);

		auto assetM = engine->GetSystem<AssetManager>().lock();
		auto inputM = engine->GetSystem<InputManager>().lock();
		auto tweener = engine->GetSystem<Tweener<float>>().lock();
		auto renderer = engine->GetSystem<Renderer>().lock();
		auto audioM = engine->GetSystem<AudioManager>().lock();

		Menu menu = {
			MenuItem("Solo Play", [engine] (Decimal) {
				engine->transition = "forward";
				return false;
			}),
			MenuItem("Options", {
				MenuItem("Graphics", {
					MenuItem("Base Detail", MenuControl::Slider<Decimal>(6, 40, renderer->GetUniformDecimal("u_baseDetail", 10)), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_baseDetail", x);
						return true;
					}),
					//MenuItem("Far Detail", MenuControl::Slider<Decimal>(), [] (Decimal) { return true; }),
					//MenuItem("Far Limiter", MenuControl::Slider<Decimal>(), [] (Decimal) { return true; }),
					//MenuItem("Precision", MenuControl::Selection({"Float", "Double"}), [] (Decimal) { return true; }),
					MenuItem("Pixel Factor", MenuControl::Slider<Decimal>(0, 20, renderer->GetUniformDecimal("u_pixelFactor", 0)), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_pixelFactor", x);
						return true;
					}),
					MenuItem("Voxel Factor", MenuControl::Slider<Decimal>(0, 20, renderer->GetUniformDecimal("u_voxelFactor", 0)), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_voxelFactor", x);
						return true;
					}),
					MenuItem("Show FPS", MenuControl::Checkbox(renderer->showFPS), [engine] (Decimal state) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->showFPS = state;
						return true;
					}),
				}),
				MenuItem("Audio", {
					MenuItem("Mute", MenuControl::Checkbox(audioM->muted), [engine] (Decimal state) {
						auto audioM = engine->GetSystem<AudioManager>().lock();
						audioM->muted = state;
						return true;
					}),
				}),
				//MenuItem("Controls", [] (Decimal) { return true; }),
				MenuItem("World", {
					MenuItem("u_baseThreshold", MenuControl::Slider<Decimal>(0, 1, renderer->GetUniformDecimal("u_baseThreshold"), 0.05), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_baseThreshold", x);
						return true;
					}),
					MenuItem("u_beatTicks", MenuControl::Slider<Decimal>(50, 10000, renderer->GetUniformDecimal("u_beatTicks"), 50), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_beatTicks", x);
						return true;
					}),
					MenuItem("u_beatPower", MenuControl::Slider<Decimal>(1, 16, renderer->GetUniformDecimal("u_beatPower")), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_beatPower", x);
						return true;
					}),
					MenuItem("u_beatStrength", MenuControl::Slider<Decimal>(-1, 1, renderer->GetUniformDecimal("u_beatStrength"), 0.002), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_beatStrength", x);
						return true;
					}),
					MenuItem("u_waveTicks", MenuControl::Slider<Decimal>(50, 10000, renderer->GetUniformDecimal("u_waveTicks"), 50), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_waveTicks", x);
						return true;
					}),
					MenuItem("u_wavePower", MenuControl::Slider<Decimal>(1, 16, renderer->GetUniformDecimal("u_wavePower")), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_wavePower", x);
						return true;
					}),
					MenuItem("u_waveStrength", MenuControl::Slider<Decimal>(-1, 1, renderer->GetUniformDecimal("u_waveStrength"), 0.002), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						renderer->SetUniform("u_waveStrength", x);
						return true;
					}),
					MenuItem("u_worldScale.x", MenuControl::Slider<Decimal>(1, 100, renderer->GetUniformPoint3("u_worldScale").x, 0.5), [engine] (Decimal x) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						auto p = renderer->GetUniformPoint3("u_worldScale");
						p.x = x;
						renderer->SetUniform("u_worldScale", p);
						return true;
					}),
					MenuItem("u_worldScale.y", MenuControl::Slider<Decimal>(1, 100, renderer->GetUniformPoint3("u_worldScale").y, 0.5), [engine] (Decimal y) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						auto p = renderer->GetUniformPoint3("u_worldScale");
						p.y = y;
						renderer->SetUniform("u_worldScale", p);
						return true;
					}),
					MenuItem("u_worldScale.z", MenuControl::Slider<Decimal>(1, 100, renderer->GetUniformPoint3("u_worldScale").z, 0.5), [engine] (Decimal z) {
						auto renderer = engine->GetSystem<Renderer>().lock();
						auto p = renderer->GetUniformPoint3("u_worldScale");
						p.z = z;
						renderer->SetUniform("u_worldScale", p);
						return true;
					}),
				}),
			}),
			MenuItem("Quit Game", [engine] (Decimal) {
				engine->Quit();
				return false;
			}),
		};
		st.AddSystem<MenuSystem>(menu);

		IDType laserID;
		st.dtors.emplace_back(engine->AddObject(&laserID));
		engine->AddComponent<AudioSource>(laserID, assetM->Get<AudioAsset>("laser"), true);

		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 1.0, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.r = x;
			renderer->SetUniform("u_color", color);
		}, 5.0 * 4 - 1.0, renderer->GetUniformPoint3("u_color").r));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.g = x;
			renderer->SetUniform("u_color", color);
		}, 5.0 * 2 - 1.0, renderer->GetUniformPoint3("u_color").g));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.b = x;
			renderer->SetUniform("u_color", color);
		}, 5.0 - 1.0, renderer->GetUniformPoint3("u_color").b));
	});

	engine.AddState("playing", [secsPerBeat, &playerID] (Polar *engine, EngineState &st) {
		st.transitions.emplace("back", Transition{Pop(), Pop(), Push("world")});

		st.AddSystem<HumanPlayerController>(playerID);

		auto assetM = engine->GetSystem<AssetManager>().lock();
		auto inputM = engine->GetSystem<InputManager>().lock();
		auto tweener = engine->GetSystem<Tweener<float>>().lock();
		auto renderer = engine->GetSystem<Renderer>().lock();

		st.dtors.emplace_back(inputM->On(Key::Escape,         [engine] (Key) { engine->transition = "back"; }));
		st.dtors.emplace_back(inputM->On(Key::ControllerBack, [engine] (Key) { engine->transition = "back"; }));

		IDType beepID;
		st.dtors.emplace_back(engine->AddObject(&beepID));
		engine->AddComponent<AudioSource>(beepID, assetM->Get<AudioAsset>("begin"));

		IDType musicID;
		st.dtors.emplace_back(engine->AddObject(&musicID));
		engine->AddComponent<AudioSource>(musicID, assetM->Get<AudioAsset>("nexus"), LoopIn{3565397});

		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.r = x;
			renderer->SetUniform("u_color", color);
		}, secsPerBeat * 4 - 0.5, renderer->GetUniformPoint3("u_color").r));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.g = x;
			renderer->SetUniform("u_color", color);
		}, secsPerBeat * 2 - 0.5, renderer->GetUniformPoint3("u_color").g));
		st.dtors.emplace_back(tweener->Tween(0.5f, 1.0f, 0.5, true, [] (Polar *engine, const float &x) {
			auto renderer = engine->GetSystem<Renderer>().lock();
			auto color = renderer->GetUniformPoint3("u_color");
			color.b = x;
			renderer->SetUniform("u_color", color);
		}, secsPerBeat - 0.5, renderer->GetUniformPoint3("u_color").b));
	});

	engine.Run("root");
}
<|endoftext|>


<commit_before>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include "gui-precomp.h"  // Precompiled headers

#if MRPT_HAS_WXWIDGETS

#include "CAboutBox_wx.h"

//(*InternalHeaders(CAboutBox)
#include <wx/artprov.h>
#include <wx/bitmap.h>
#include <wx/font.h>
#include <wx/intl.h>
#include <wx/image.h>
#include <wx/string.h>
//*)

#include <mrpt/gui/CMyRedirector.h>
#include <mrpt/gui/WxUtils.h>  // _U()

// For CV_VERSION
#include <mrpt/config.h>

#include <mrpt/system/os.h>

using namespace mrpt;
using namespace mrpt::system;
using namespace std;

//(*IdInit(CAboutBox)
const long CAboutBox::ID_STATICTEXT1 = wxNewId();
const long CAboutBox::ID_STATICTEXT2 = wxNewId();
const long CAboutBox::ID_STATICBITMAP1 = wxNewId();
const long CAboutBox::ID_STATICLINE1 = wxNewId();
const long CAboutBox::ID_TEXTCTRL1 = wxNewId();
const long CAboutBox::ID_TEXTCTRL2 = wxNewId();
const long CAboutBox::ID_TEXTCTRL3 = wxNewId();
const long CAboutBox::ID_NOTEBOOK1 = wxNewId();
const long CAboutBox::ID_BUTTON1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(CAboutBox, wxDialog)
//(*EventTable(CAboutBox)
//*)
END_EVENT_TABLE()

CAboutBox::CAboutBox(
	wxWindow* parent, const std::string& appName,
	const std::string& additionalInfo, const bool showStandardInfo)
	: CAboutBoxBase(appName, additionalInfo, showStandardInfo)
{
	const wxWindowID id = -1;
	//(*Initialize(CAboutBox)
	wxFlexGridSizer* FlexGridSizer2;

	Create(
		parent, id, _("About box..."), wxDefaultPosition, wxDefaultSize,
		wxDEFAULT_DIALOG_STYLE | wxCLOSE_BOX, _T("id"));
	SetClientSize(wxSize(636, 375));
	FlexGridSizer1 = new wxFlexGridSizer(0, 1, 0, 0);
	FlexGridSizer1->AddGrowableCol(0);
	FlexGridSizer4 = new wxFlexGridSizer(0, 2, 0, 0);
	FlexGridSizer4->AddGrowableCol(1);
	FlexGridSizer4->AddGrowableRow(0);
	FlexGridSizer2 = new wxFlexGridSizer(2, 1, 0, 0);
	FlexGridSizer2->AddGrowableCol(0);
	FlexGridSizer2->AddGrowableRow(0);
	FlexGridSizer2->AddGrowableRow(1);
	lbProgName = new wxStaticText(
		this, ID_STATICTEXT1, _("Title"), wxDefaultPosition, wxDefaultSize, 0,
		_T("ID_STATICTEXT1"));
	wxFont lbProgNameFont(
		22, wxSWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false,
		_T("Times New Roman"), wxFONTENCODING_DEFAULT);
	lbProgName->SetFont(lbProgNameFont);
	FlexGridSizer2->Add(
		lbProgName, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
	lbBuild = new wxStaticText(
		this, ID_STATICTEXT2, _("Label"), wxDefaultPosition, wxDefaultSize, 0,
		_T("ID_STATICTEXT2"));
	FlexGridSizer2->Add(
		lbBuild, 1, wxALL | wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL, 5);
	FlexGridSizer4->Add(
		FlexGridSizer2, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 0);
	StaticBitmap1 = new wxStaticBitmap(
		this, ID_STATICBITMAP1,
		wxArtProvider::GetBitmap(
			wxART_MAKE_ART_ID_FROM_STR(_T("IMG_MRPT_LOGO")), wxART_OTHER),
		wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICBITMAP1"));
	FlexGridSizer4->Add(
		StaticBitmap1, 1,
		wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
	FlexGridSizer1->Add(
		FlexGridSizer4, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 1);
	StaticLine1 = new wxStaticLine(
		this, ID_STATICLINE1, wxPoint(3, 86), wxSize(627, 2), wxLI_HORIZONTAL,
		_T("ID_STATICLINE1"));
	FlexGridSizer1->Add(
		StaticLine1, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 5);
	Notebook1 = new wxNotebook(
		this, ID_NOTEBOOK1, wxPoint(6, 91), wxSize(625, 250), 0,
		_T("ID_NOTEBOOK1"));
	lbInfo = new wxTextCtrl(
		Notebook1, ID_TEXTCTRL1, wxEmptyString, wxPoint(4, 24),
		wxSize(545, 250), wxTE_MULTILINE | wxTE_READONLY | wxTE_AUTO_URL,
		wxDefaultValidator, _T("ID_TEXTCTRL1"));
	wxFont lbInfoFont(
		10, wxSWISS, wxFONTSTYLE_NORMAL, wxNORMAL, false, _T("Courier New"),
		wxFONTENCODING_DEFAULT);
	lbInfo->SetFont(lbInfoFont);
	lbLicense = new wxTextCtrl(
		Notebook1, ID_TEXTCTRL2, _(""), wxDefaultPosition, wxDefaultSize,
		wxTE_MULTILINE | wxTE_READONLY | wxTE_AUTO_URL, wxDefaultValidator,
		_T("ID_TEXTCTRL2"));
	wxFont lbLicenseFont(
		10, wxSWISS, wxFONTSTYLE_NORMAL, wxNORMAL, false, _T("Courier New"),
		wxFONTENCODING_DEFAULT);
	lbLicense->SetFont(lbLicenseFont);
	TextCtrl1 = new wxTextCtrl(
		Notebook1, ID_TEXTCTRL3, _U(tutorial().c_str()), wxPoint(4, 24),
		wxSize(545, 222), wxTE_MULTILINE | wxTE_READONLY | wxTE_AUTO_URL,
		wxDefaultValidator, _T("ID_TEXTCTRL3"));
	wxFont TextCtrl1Font(
		10, wxSWISS, wxFONTSTYLE_NORMAL, wxNORMAL, false, _T("Courier New"),
		wxFONTENCODING_DEFAULT);
	TextCtrl1->SetFont(TextCtrl1Font);
	Notebook1->AddPage(lbInfo, _("Information"), false);
	Notebook1->AddPage(lbLicense, _("License"), false);
	Notebook1->AddPage(TextCtrl1, _("Tutorial"), false);
	FlexGridSizer1->Add(
		Notebook1, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 5);
	Button11 = new wxButton(
		this, ID_BUTTON1, _("OK"), wxPoint(250, 345), wxSize(76, 26), 0,
		wxDefaultValidator, _T("ID_BUTTON1"));
	FlexGridSizer1->Add(
		Button11, 1,
		wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
	SetSizer(FlexGridSizer1);
	FlexGridSizer1->SetSizeHints(this);
	Center();

	Connect(
		ID_BUTTON1, wxEVT_COMMAND_BUTTON_CLICKED,
		(wxObjectEventFunction)&CAboutBox::OnButton1Click);
	Connect(
		wxID_ANY, wxEVT_INIT_DIALOG, (wxObjectEventFunction)&CAboutBox::OnInit);
	//*)

	lbLicense->SetValue(_U(license().c_str()));
}

CAboutBox::~CAboutBox()
{
	//(*Destroy(CAboutBox)
	//*)
}

void CAboutBox::OnInit(wxInitDialogEvent& event)
{
	// Build strings:
	wxString MRPTver(MRPT_getVersion().c_str(), wxConvLibc);

	// Set the label with MRPT version:
	wxString s(_("Build: "));
	s << _U(mrpt::system::MRPT_getCompilationDate().c_str());
	s << _(" - ") << MRPTver;

	lbBuild->SetLabel(s);

	// Info:
	lbInfo->Clear();

	{
		CMyRedirector myRedirector(lbInfo);
		wxString wxVer(wxVERSION_STRING);
		cout << information("wxWidgets", std::string(wxVer.mb_str()));
	}

	lbProgName->SetLabel(_U(m_appName.c_str()));
	lbProgName->SetForegroundColour(wxColour(0, 0, 128));

	FlexGridSizer1->RecalcSizes();
	this->Fit();
}

void CAboutBox::OnButton1Click(wxCommandEvent& event) { Close(); }
#endif  // MRPT_HAS_WXWIDGETS
<commit_msg>deprecated wx3 constants<commit_after>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include "gui-precomp.h"  // Precompiled headers

#if MRPT_HAS_WXWIDGETS

#include "CAboutBox_wx.h"

//(*InternalHeaders(CAboutBox)
#include <wx/artprov.h>
#include <wx/bitmap.h>
#include <wx/font.h>
#include <wx/intl.h>
#include <wx/image.h>
#include <wx/string.h>
//*)

#include <mrpt/gui/CMyRedirector.h>
#include <mrpt/gui/WxUtils.h>  // _U()

// For CV_VERSION
#include <mrpt/config.h>

#include <mrpt/system/os.h>

using namespace mrpt;
using namespace mrpt::system;
using namespace std;

//(*IdInit(CAboutBox)
const long CAboutBox::ID_STATICTEXT1 = wxNewId();
const long CAboutBox::ID_STATICTEXT2 = wxNewId();
const long CAboutBox::ID_STATICBITMAP1 = wxNewId();
const long CAboutBox::ID_STATICLINE1 = wxNewId();
const long CAboutBox::ID_TEXTCTRL1 = wxNewId();
const long CAboutBox::ID_TEXTCTRL2 = wxNewId();
const long CAboutBox::ID_TEXTCTRL3 = wxNewId();
const long CAboutBox::ID_NOTEBOOK1 = wxNewId();
const long CAboutBox::ID_BUTTON1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(CAboutBox, wxDialog)
//(*EventTable(CAboutBox)
//*)
END_EVENT_TABLE()

CAboutBox::CAboutBox(
	wxWindow* parent, const std::string& appName,
	const std::string& additionalInfo, const bool showStandardInfo)
	: CAboutBoxBase(appName, additionalInfo, showStandardInfo)
{
	const wxWindowID id = -1;
	//(*Initialize(CAboutBox)
	wxFlexGridSizer* FlexGridSizer2;

	Create(
		parent, id, _("About box..."), wxDefaultPosition, wxDefaultSize,
		wxDEFAULT_DIALOG_STYLE | wxCLOSE_BOX, _T("id"));
	SetClientSize(wxSize(636, 375));
	FlexGridSizer1 = new wxFlexGridSizer(0, 1, 0, 0);
	FlexGridSizer1->AddGrowableCol(0);
	FlexGridSizer4 = new wxFlexGridSizer(0, 2, 0, 0);
	FlexGridSizer4->AddGrowableCol(1);
	FlexGridSizer4->AddGrowableRow(0);
	FlexGridSizer2 = new wxFlexGridSizer(2, 1, 0, 0);
	FlexGridSizer2->AddGrowableCol(0);
	FlexGridSizer2->AddGrowableRow(0);
	FlexGridSizer2->AddGrowableRow(1);
	lbProgName = new wxStaticText(
		this, ID_STATICTEXT1, _("Title"), wxDefaultPosition, wxDefaultSize, 0,
		_T("ID_STATICTEXT1"));
	wxFont lbProgNameFont(
		22, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false,
		_T("Times New Roman"), wxFONTENCODING_DEFAULT);
	lbProgName->SetFont(lbProgNameFont);
	FlexGridSizer2->Add(
		lbProgName, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
	lbBuild = new wxStaticText(
		this, ID_STATICTEXT2, _("Label"), wxDefaultPosition, wxDefaultSize, 0,
		_T("ID_STATICTEXT2"));
	FlexGridSizer2->Add(
		lbBuild, 1, wxALL | wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL, 5);
	FlexGridSizer4->Add(
		FlexGridSizer2, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 0);
	StaticBitmap1 = new wxStaticBitmap(
		this, ID_STATICBITMAP1,
		wxArtProvider::GetBitmap(
			wxART_MAKE_ART_ID_FROM_STR(_T("IMG_MRPT_LOGO")), wxART_OTHER),
		wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICBITMAP1"));
	FlexGridSizer4->Add(
		StaticBitmap1, 1,
		wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
	FlexGridSizer1->Add(
		FlexGridSizer4, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 1);
	StaticLine1 = new wxStaticLine(
		this, ID_STATICLINE1, wxPoint(3, 86), wxSize(627, 2), wxLI_HORIZONTAL,
		_T("ID_STATICLINE1"));
	FlexGridSizer1->Add(
		StaticLine1, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 5);
	Notebook1 = new wxNotebook(
		this, ID_NOTEBOOK1, wxPoint(6, 91), wxSize(625, 250), 0,
		_T("ID_NOTEBOOK1"));
	lbInfo = new wxTextCtrl(
		Notebook1, ID_TEXTCTRL1, wxEmptyString, wxPoint(4, 24),
		wxSize(545, 250), wxTE_MULTILINE | wxTE_READONLY | wxTE_AUTO_URL,
		wxDefaultValidator, _T("ID_TEXTCTRL1"));
	wxFont lbInfoFont(
		10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false,
		_T("Courier New"), wxFONTENCODING_DEFAULT);
	lbInfo->SetFont(lbInfoFont);
	lbLicense = new wxTextCtrl(
		Notebook1, ID_TEXTCTRL2, _(""), wxDefaultPosition, wxDefaultSize,
		wxTE_MULTILINE | wxTE_READONLY | wxTE_AUTO_URL, wxDefaultValidator,
		_T("ID_TEXTCTRL2"));
	wxFont lbLicenseFont(
		10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false,
		_T("Courier New"), wxFONTENCODING_DEFAULT);
	lbLicense->SetFont(lbLicenseFont);
	TextCtrl1 = new wxTextCtrl(
		Notebook1, ID_TEXTCTRL3, _U(tutorial().c_str()), wxPoint(4, 24),
		wxSize(545, 222), wxTE_MULTILINE | wxTE_READONLY | wxTE_AUTO_URL,
		wxDefaultValidator, _T("ID_TEXTCTRL3"));
	wxFont TextCtrl1Font(
		10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false,
		_T("Courier New"), wxFONTENCODING_DEFAULT);
	TextCtrl1->SetFont(TextCtrl1Font);
	Notebook1->AddPage(lbInfo, _("Information"), false);
	Notebook1->AddPage(lbLicense, _("License"), false);
	Notebook1->AddPage(TextCtrl1, _("Tutorial"), false);
	FlexGridSizer1->Add(
		Notebook1, 1, wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 5);
	Button11 = new wxButton(
		this, ID_BUTTON1, _("OK"), wxPoint(250, 345), wxSize(76, 26), 0,
		wxDefaultValidator, _T("ID_BUTTON1"));
	FlexGridSizer1->Add(
		Button11, 1,
		wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
	SetSizer(FlexGridSizer1);
	FlexGridSizer1->SetSizeHints(this);
	Center();

	Connect(
		ID_BUTTON1, wxEVT_COMMAND_BUTTON_CLICKED,
		(wxObjectEventFunction)&CAboutBox::OnButton1Click);
	Connect(
		wxID_ANY, wxEVT_INIT_DIALOG, (wxObjectEventFunction)&CAboutBox::OnInit);
	//*)

	lbLicense->SetValue(_U(license().c_str()));
}

CAboutBox::~CAboutBox()
{
	//(*Destroy(CAboutBox)
	//*)
}

void CAboutBox::OnInit(wxInitDialogEvent& event)
{
	// Build strings:
	wxString MRPTver(MRPT_getVersion().c_str(), wxConvLibc);

	// Set the label with MRPT version:
	wxString s(_("Build: "));
	s << _U(mrpt::system::MRPT_getCompilationDate().c_str());
	s << _(" - ") << MRPTver;

	lbBuild->SetLabel(s);

	// Info:
	lbInfo->Clear();

	{
		CMyRedirector myRedirector(lbInfo);
		wxString wxVer(wxVERSION_STRING);
		cout << information("wxWidgets", std::string(wxVer.mb_str()));
	}

	lbProgName->SetLabel(_U(m_appName.c_str()));
	lbProgName->SetForegroundColour(wxColour(0, 0, 128));

	FlexGridSizer1->RecalcSizes();
	this->Fit();
}

void CAboutBox::OnButton1Click(wxCommandEvent& event) { Close(); }
#endif  // MRPT_HAS_WXWIDGETS
<|endoftext|>


<commit_before>#ifndef SAMPLE_UTIL_HPP
#define SAMPLE_UTIL_HPP

#include "ranger/bhvr_tree/agent_proxy.hpp"
#include "ranger/bhvr_tree/abstract_node.hpp"
#include <caf/all.hpp>
#include <sstream>
#include <thread>
#include <chrono>

namespace std {

inline std::string to_string(const std::thread::id& tid) {
	std::stringstream ss;
	ss << tid;
	return ss.str();
}

}

using true_atom = caf::atom_constant<caf::atom("true")>;
using false_atom = caf::atom_constant<caf::atom("false")>;
using result_actor = caf::typed_actor<	caf::replies_to<true_atom>::with<bool>,
										caf::replies_to<false_atom>::with<bool>	>;

result_actor::behavior_type result_actor_impl(result_actor::pointer self) {
	return {
		[=] (true_atom) {
			return true;
		},
		[=] (false_atom) {
			return false;
		},
		caf::after(std::chrono::seconds(3)) >> [=] {
			self->quit();
		}
	};
}

template <class Atom>
class behavior_node : public ranger::bhvr_tree::abstract_node<void> {
public:
	behavior_node() : m_target(caf::spawn(result_actor_impl)) {
		// nop
	}

	void exec(ranger::bhvr_tree::agent_proxy<void>& ap, std::function<void(bool)> hdl) final {
		std::cout << "behavior_node::exec" << std::endl;
		caf::spawn([this, hdl] (caf::event_based_actor* self) {
			self->sync_send(m_target, Atom::value).then(
				[=] (bool result) {
					caf::aout(self) << std::this_thread::get_id() << std::endl;
					hdl(result);
				}
			);
		});
	}

private:
	result_actor m_target;
};

using true_node = behavior_node<true_atom>;
using false_node = behavior_node<false_atom>;

#endif	// SAMPLE_UTIL_HPP
<commit_msg>移除Sample中线程id的打印逻辑<commit_after>#ifndef SAMPLE_UTIL_HPP
#define SAMPLE_UTIL_HPP

#include "ranger/bhvr_tree/agent_proxy.hpp"
#include "ranger/bhvr_tree/abstract_node.hpp"
#include <caf/all.hpp>
#include <chrono>

using true_atom = caf::atom_constant<caf::atom("true")>;
using false_atom = caf::atom_constant<caf::atom("false")>;
using result_actor = caf::typed_actor<	caf::replies_to<true_atom>::with<bool>,
										caf::replies_to<false_atom>::with<bool>	>;

result_actor::behavior_type result_actor_impl(result_actor::pointer self) {
	return {
		[=] (true_atom) {
			return true;
		},
		[=] (false_atom) {
			return false;
		},
		caf::after(std::chrono::seconds(3)) >> [=] {
			self->quit();
		}
	};
}

template <class Atom>
class behavior_node : public ranger::bhvr_tree::abstract_node<void> {
public:
	behavior_node() : m_target(caf::spawn(result_actor_impl)) {
		// nop
	}

	void exec(ranger::bhvr_tree::agent_proxy<void>& ap, std::function<void(bool)> hdl) final {
		std::cout << "behavior_node::exec" << std::endl;
		caf::spawn([this, hdl] (caf::event_based_actor* self) {
			self->sync_send(m_target, Atom::value).then(
				[=] (bool result) {
					hdl(result);
				}
			);
		});
	}

private:
	result_actor m_target;
};

using true_node = behavior_node<true_atom>;
using false_node = behavior_node<false_atom>;

#endif	// SAMPLE_UTIL_HPP
<|endoftext|>