<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<char *>(region))
    , end_(begin_ + size)
  {}

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

  /**
   * Return byte pointer to end of region.
   */
  uint8_t *end () const noexcept
  {
    return reinterpret_cast<uint8_t *>(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:

  char *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 area is initialized
  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 area is initialized
  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 char *>(region))
    , end_(begin_ + size)
  {}

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

  /**
   * Return byte pointer to end of region.
   */
  const uint8_t *end () const noexcept
  {
    return reinterpret_cast<const uint8_t *>(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 char *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: drop reinterpret_cast as much as possible<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_{};
};

/**
 * 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
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/
#include "precomp.hpp"

int cv::meanShift( InputArray _probImage, Rect& window, TermCriteria criteria )
{
    CV_INSTRUMENT_REGION();

    Size size;
    int cn;
    Mat mat;
    UMat umat;
    bool isUMat = _probImage.isUMat();

    if (isUMat)
        umat = _probImage.getUMat(), cn = umat.channels(), size = umat.size();
    else
        mat = _probImage.getMat(), cn = mat.channels(), size = mat.size();

    Rect cur_rect = window;

    CV_Assert( cn == 1 );

    if( window.height <= 0 || window.width <= 0 )
        CV_Error( Error::StsBadArg, "Input window has non-positive sizes" );

    window = window & Rect(0, 0, size.width, size.height);

    double eps = (criteria.type & TermCriteria::EPS) ? std::max(criteria.epsilon, 0.) : 1.;
    eps = cvRound(eps*eps);
    int i, niters = (criteria.type & TermCriteria::MAX_ITER) ? std::max(criteria.maxCount, 1) : 100;

    for( i = 0; i < niters; i++ )
    {
        cur_rect = cur_rect & Rect(0, 0, size.width, size.height);
        if( cur_rect == Rect() )
        {
            cur_rect.x = size.width/2;
            cur_rect.y = size.height/2;
        }
        cur_rect.width = std::max(cur_rect.width, 1);
        cur_rect.height = std::max(cur_rect.height, 1);

        Moments m = isUMat ? moments(umat(cur_rect)) : moments(mat(cur_rect));

        // Calculating center of mass
        if( fabs(m.m00) < DBL_EPSILON )
            break;

        int dx = cvRound( m.m10/m.m00 - window.width*0.5 );
        int dy = cvRound( m.m01/m.m00 - window.height*0.5 );

        int nx = std::min(std::max(cur_rect.x + dx, 0), size.width - cur_rect.width);
        int ny = std::min(std::max(cur_rect.y + dy, 0), size.height - cur_rect.height);

        dx = nx - cur_rect.x;
        dy = ny - cur_rect.y;
        cur_rect.x = nx;
        cur_rect.y = ny;

        // Check for coverage centers mass & window
        if( dx*dx + dy*dy < eps )
            break;
    }

    window = cur_rect;
    return i;
}

cv::RotatedRect cv::CamShift( InputArray _probImage, Rect& window,
                              TermCriteria criteria )
{
    CV_INSTRUMENT_REGION();

    const int TOLERANCE = 10;
    Size size;
    Mat mat;
    UMat umat;
    bool isUMat = _probImage.isUMat();

    if (isUMat)
        umat = _probImage.getUMat(), size = umat.size();
    else
        mat = _probImage.getMat(), size = mat.size();

    meanShift( _probImage, window, criteria );

    window.x -= TOLERANCE;
    if( window.x < 0 )
        window.x = 0;

    window.y -= TOLERANCE;
    if( window.y < 0 )
        window.y = 0;

    window.width += 2 * TOLERANCE;
    if( window.x + window.width > size.width )
        window.width = size.width - window.x;

    window.height += 2 * TOLERANCE;
    if( window.y + window.height > size.height )
        window.height = size.height - window.y;

    // Calculating moments in new center mass
    Moments m = isUMat ? moments(umat(window)) : moments(mat(window));

    double m00 = m.m00, m10 = m.m10, m01 = m.m01;
    double mu11 = m.mu11, mu20 = m.mu20, mu02 = m.mu02;

    if( fabs(m00) < DBL_EPSILON )
        return RotatedRect();

    double inv_m00 = 1. / m00;
    int xc = cvRound( m10 * inv_m00 + window.x );
    int yc = cvRound( m01 * inv_m00 + window.y );
    double a = mu20 * inv_m00, b = mu11 * inv_m00, c = mu02 * inv_m00;

    // Calculating width & height
    double square = std::sqrt( 4 * b * b + (a - c) * (a - c) );

    // Calculating orientation
    double theta = atan2( 2 * b, a - c + square );

    // Calculating width & length of figure
    double cs = cos( theta );
    double sn = sin( theta );

    double rotate_a = cs * cs * mu20 + 2 * cs * sn * mu11 + sn * sn * mu02;
    double rotate_c = sn * sn * mu20 - 2 * cs * sn * mu11 + cs * cs * mu02;
    double length = std::sqrt( rotate_a * inv_m00 ) * 4;
    double width = std::sqrt( rotate_c * inv_m00 ) * 4;

    // In case, when tetta is 0 or 1.57... the Length & Width may be exchanged
    if( length < width )
    {
        std::swap( length, width );
        std::swap( cs, sn );
        theta = CV_PI*0.5 - theta;
    }

    // Saving results
    int _xc = cvRound( xc );
    int _yc = cvRound( yc );

    int t0 = cvRound( fabs( length * cs ));
    int t1 = cvRound( fabs( width * sn ));

    t0 = MAX( t0, t1 ) + 2;
    window.width = MIN( t0, (size.width - _xc) * 2 );

    t0 = cvRound( fabs( length * sn ));
    t1 = cvRound( fabs( width * cs ));

    t0 = MAX( t0, t1 ) + 2;
    window.height = MIN( t0, (size.height - _yc) * 2 );

    window.x = MAX( 0, _xc - window.width / 2 );
    window.y = MAX( 0, _yc - window.height / 2 );

    window.width = MIN( size.width - window.x, window.width );
    window.height = MIN( size.height - window.y, window.height );

    RotatedRect box;
    box.size.height = (float)length;
    box.size.width = (float)width;
    box.angle = (float)((CV_PI*0.5+theta)*180./CV_PI);
    while(box.angle < 0)
        box.angle += 360;
    while(box.angle >= 360)
        box.angle -= 360;
    if(box.angle >= 180)
        box.angle -= 180;
    box.center = Point2f( window.x + window.width*0.5f, window.y + window.height*0.5f);

    return box;
}

/* End of file. */
<commit_msg> fixed bug: added threshold for variables 'rotate_a', ' rotate_c'<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/
#include "precomp.hpp"

int cv::meanShift( InputArray _probImage, Rect& window, TermCriteria criteria )
{
    CV_INSTRUMENT_REGION();

    Size size;
    int cn;
    Mat mat;
    UMat umat;
    bool isUMat = _probImage.isUMat();

    if (isUMat)
        umat = _probImage.getUMat(), cn = umat.channels(), size = umat.size();
    else
        mat = _probImage.getMat(), cn = mat.channels(), size = mat.size();

    Rect cur_rect = window;

    CV_Assert( cn == 1 );

    if( window.height <= 0 || window.width <= 0 )
        CV_Error( Error::StsBadArg, "Input window has non-positive sizes" );

    window = window & Rect(0, 0, size.width, size.height);

    double eps = (criteria.type & TermCriteria::EPS) ? std::max(criteria.epsilon, 0.) : 1.;
    eps = cvRound(eps*eps);
    int i, niters = (criteria.type & TermCriteria::MAX_ITER) ? std::max(criteria.maxCount, 1) : 100;

    for( i = 0; i < niters; i++ )
    {
        cur_rect = cur_rect & Rect(0, 0, size.width, size.height);
        if( cur_rect == Rect() )
        {
            cur_rect.x = size.width/2;
            cur_rect.y = size.height/2;
        }
        cur_rect.width = std::max(cur_rect.width, 1);
        cur_rect.height = std::max(cur_rect.height, 1);

        Moments m = isUMat ? moments(umat(cur_rect)) : moments(mat(cur_rect));

        // Calculating center of mass
        if( fabs(m.m00) < DBL_EPSILON )
            break;

        int dx = cvRound( m.m10/m.m00 - window.width*0.5 );
        int dy = cvRound( m.m01/m.m00 - window.height*0.5 );

        int nx = std::min(std::max(cur_rect.x + dx, 0), size.width - cur_rect.width);
        int ny = std::min(std::max(cur_rect.y + dy, 0), size.height - cur_rect.height);

        dx = nx - cur_rect.x;
        dy = ny - cur_rect.y;
        cur_rect.x = nx;
        cur_rect.y = ny;

        // Check for coverage centers mass & window
        if( dx*dx + dy*dy < eps )
            break;
    }

    window = cur_rect;
    return i;
}

cv::RotatedRect cv::CamShift( InputArray _probImage, Rect& window,
                              TermCriteria criteria )
{
    CV_INSTRUMENT_REGION();

    const int TOLERANCE = 10;
    Size size;
    Mat mat;
    UMat umat;
    bool isUMat = _probImage.isUMat();

    if (isUMat)
        umat = _probImage.getUMat(), size = umat.size();
    else
        mat = _probImage.getMat(), size = mat.size();

    meanShift( _probImage, window, criteria );

    window.x -= TOLERANCE;
    if( window.x < 0 )
        window.x = 0;

    window.y -= TOLERANCE;
    if( window.y < 0 )
        window.y = 0;

    window.width += 2 * TOLERANCE;
    if( window.x + window.width > size.width )
        window.width = size.width - window.x;

    window.height += 2 * TOLERANCE;
    if( window.y + window.height > size.height )
        window.height = size.height - window.y;

    // Calculating moments in new center mass
    Moments m = isUMat ? moments(umat(window)) : moments(mat(window));

    double m00 = m.m00, m10 = m.m10, m01 = m.m01;
    double mu11 = m.mu11, mu20 = m.mu20, mu02 = m.mu02;

    if( fabs(m00) < DBL_EPSILON )
        return RotatedRect();

    double inv_m00 = 1. / m00;
    int xc = cvRound( m10 * inv_m00 + window.x );
    int yc = cvRound( m01 * inv_m00 + window.y );
    double a = mu20 * inv_m00, b = mu11 * inv_m00, c = mu02 * inv_m00;

    // Calculating width & height
    double square = std::sqrt( 4 * b * b + (a - c) * (a - c) );

    // Calculating orientation
    double theta = atan2( 2 * b, a - c + square );

    // Calculating width & length of figure
    double cs = cos( theta );
    double sn = sin( theta );

    double rotate_a = cs * cs * mu20 + 2 * cs * sn * mu11 + sn * sn * mu02;
    double rotate_c = sn * sn * mu20 - 2 * cs * sn * mu11 + cs * cs * mu02;
    rotate_a = std::max(0.0, rotate_a);  // avoid negative result due calculation numeric errors
    rotate_c = std::max(0.0, rotate_c);  // avoid negative result due calculation numeric errors
    double length = std::sqrt( rotate_a * inv_m00 ) * 4;
    double width = std::sqrt( rotate_c * inv_m00 ) * 4;

    // In case, when tetta is 0 or 1.57... the Length & Width may be exchanged
    if( length < width )
    {
        std::swap( length, width );
        std::swap( cs, sn );
        theta = CV_PI*0.5 - theta;
    }

    // Saving results
    int _xc = cvRound( xc );
    int _yc = cvRound( yc );

    int t0 = cvRound( fabs( length * cs ));
    int t1 = cvRound( fabs( width * sn ));

    t0 = MAX( t0, t1 ) + 2;
    window.width = MIN( t0, (size.width - _xc) * 2 );

    t0 = cvRound( fabs( length * sn ));
    t1 = cvRound( fabs( width * cs ));

    t0 = MAX( t0, t1 ) + 2;
    window.height = MIN( t0, (size.height - _yc) * 2 );

    window.x = MAX( 0, _xc - window.width / 2 );
    window.y = MAX( 0, _yc - window.height / 2 );

    window.width = MIN( size.width - window.x, window.width );
    window.height = MIN( size.height - window.y, window.height );

    RotatedRect box;
    box.size.height = (float)length;
    box.size.width = (float)width;
    box.angle = (float)((CV_PI*0.5+theta)*180./CV_PI);
    while(box.angle < 0)
        box.angle += 360;
    while(box.angle >= 360)
        box.angle -= 360;
    if(box.angle >= 180)
        box.angle -= 180;
    box.center = Point2f( window.x + window.width*0.5f, window.y + window.height*0.5f);

    return box;
}

/* End of file. */
<|endoftext|>


<commit_before>#include "kernel.h"
#include "ilwisdata.h"
#include "domain.h"
#include "range.h"
#include "datadefinition.h"
#include "columndefinition.h"
#include "connectorinterface.h"
#include "domainitem.h"
#include "basetable.h"
#include "flattable.h"
#include "tablemerger.h"
#include "itemrange.h"
#include "logicalexpressionparser.h"
#include "tableselector.h"

using namespace Ilwis;

FlatTable::FlatTable()
{
}

FlatTable::FlatTable(const Resource& resource) : BaseTable(resource){

}

FlatTable::~FlatTable()
{
    _datagrid.clear();
}

bool FlatTable::createTable()
{
    if(!BaseTable::createTable())
        return false;
    for(unsigned int i=0; i < recordCount(); ++i)
        _datagrid.push_back(std::vector<QVariant>(_columnDefinitionsByIndex.size()));
    return true;
}

quint32 FlatTable::newRecord()
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return iUNDEF;

    std::vector<QVariant> values;
    initRecord(values);
    record(NEW_RECORD, values);

    return recordCount() - 1;
}

void FlatTable::removeRecord(quint32 rec)
{
    if ( rec < recordCount()){
        _datagrid.erase(_datagrid.begin() + rec);
    }
}

bool FlatTable::prepare()
{
    return Table::prepare();
}

bool FlatTable::isValid() const
{
    return Table::isValid();
}

bool FlatTable::addColumn(const QString &name, const IDomain &domain)
{
    bool ok = BaseTable::addColumn(name, domain);
    if(!ok)
        return false;
    if ( isDataLoaded()){
        for(Record& row : _datagrid) {
            row.addColumn();
            row.changed(true);
        }
        initValuesColumn(name);
    }
    return true;

}

bool FlatTable::addColumn(const ColumnDefinition &def)
{
    bool ok = BaseTable::addColumn(def);
    if(!ok)
        return false;
    if (  isDataLoaded()) {
        for(Record& row : _datagrid) {
            row.addColumn();
            row.changed(true);
        }
        initValuesColumn(def.name());
    }
    return true;
}

std::vector<QVariant> FlatTable::column(quint32 index, quint32 start, quint32 stop) const {
    if (!const_cast<FlatTable *>(this)->initLoad())
        return std::vector<QVariant>();

    if ( !isColumnIndexValid(index))
        return std::vector<QVariant>();

    stop = std::min(stop, recordCount());
    start = std::max((quint32)0, start);
    std::vector<QVariant> data(stop - start);
    for(quint32 i=start; i < stop; ++i) {
        data[i - start] = _datagrid[i].cell(index);
    }
    return data;
}

std::vector<QVariant> FlatTable::column(const QString &nme, quint32 start, quint32 stop) const
{
    quint32 index = columnIndex(nme);
    return column(index, start, stop);

}

void FlatTable::column(quint32 index, const std::vector<QVariant> &vars, quint32 offset)
{
    if (index >= columnCount()) {
        ERROR2(ERR_ILLEGAL_VALUE_2,"Column index", name());
        return ;
    }
    column( _columnDefinitionsByIndex[index].name(), vars, offset);
}

void FlatTable::column(const QString &nme, const std::vector<QVariant> &vars, quint32 offset)
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( isReadOnly())
        return ;
    changed(true);

    quint32 index = columnIndex(nme);
    if ( !isColumnIndexValid(index))
        return ;

    quint32 rec = offset;
    _columnDefinitionsByIndex[index].changed(true);
    for(const QVariant& var : vars) {
        if ( rec < _datagrid.size()){
            _datagrid[rec].changed(true);
            _datagrid[rec++].cell(index, var);
        }
        else {
            _datagrid.push_back(std::vector<QVariant>(_columnDefinitionsByIndex.size()));
            _datagrid[rec].changed(true);
            _datagrid[rec++].cell(index,checkInput(var,index));
            recordCount(_datagrid.size());
        }
    }

}

const Record& FlatTable::record(quint32 rec) const{
    if (!const_cast<FlatTable *>(this)->initLoad())
        throw ErrorObject(QString(TR("failed load of table %1")).arg(name()));

    if ( rec < recordCount() && _datagrid.size() != 0) {
         return _datagrid[rec];
    }
    throw ErrorObject(QString("Requested record number is not in the table").arg(rec));
}

Record& FlatTable::recordRef(quint32 rec)
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        throw ErrorObject(QString(TR("failed load of table %1")).arg(name()));

    if ( rec < recordCount() && _datagrid.size() != 0) {
         return _datagrid[rec];
    }
    throw ErrorObject(QString("Requested record number is not in the table").arg(rec));
}

void FlatTable::record(quint32 rec, const std::vector<QVariant>& vars, quint32 offset)
{

    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( isReadOnly())
        return ;
    changed(true);
    if ( rec >=recordCount() ) {
        _datagrid.push_back(std::vector<QVariant>(_columnDefinitionsByIndex.size()));
        _datagrid.back().changed(true);
        recordCount(_datagrid.size());
        rec = recordCount() - 1;
    }
    quint32 col = offset;
    int cols = std::min((quint32)vars.size() - offset, columnCount());
    for(const QVariant& var : vars) {
        if ( col < cols){
            _datagrid[rec].changed(true);
            _datagrid[rec].cell(col, checkInput(var, col));
            ++col;
        }
    }

}

QVariant FlatTable::cell(const QString& col, quint32 rec, bool asRaw) const {
    if (!const_cast<FlatTable *>(this)->initLoad())
        return QVariant();
    quint32 index = columnIndex(col);
    return cell(index , rec, asRaw);
}

QVariant FlatTable::cell(const quint32 index, quint32 rec, bool asRaw) const
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return QVariant();

    if ( !isColumnIndexValid(index))
        return QVariant();
    if ( rec < recordCount()) {
        QVariant var = _datagrid[rec].cell(index);
        if ( !asRaw) {
            ColumnDefinition coldef = columndefinition(index);
            return coldef.datadef().domain<>()->impliedValue(var);
        }
        return var;
    }
    kernel()->issues()->log(TR(ERR_INVALID_RECORD_SIZE_IN).arg(name()),IssueObject::itWarning);
    return QVariant();
}

void  FlatTable::setCell(quint32 index, quint32 rec, const QVariant& var){
    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( !isColumnIndexValid(index))
        return;

    if ( isReadOnly())
        return ;
    changed(true);

    _columnDefinitionsByIndex[index].changed(true);

    if ( rec >= recordCount()) {
        newRecord();
    }
    _datagrid[rec].cell(index, checkInput(var, index));
    _datagrid[rec].changed(true);

}

void FlatTable::setCell(const QString &col, quint32 rec, const QVariant &var)
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( isReadOnly())
        return ;
    changed(true);

    quint32 index = columnIndex(col);
    setCell(index, rec, var);

}

IlwisTypes FlatTable::ilwisType() const
{
    return itFLATTABLE;
}

IlwisObject *FlatTable::clone()
{
    if (initLoad()){
        FlatTable *tbl = new FlatTable();
        copyTo(tbl);
        tbl->_datagrid = _datagrid;
        for(auto& record : tbl->_datagrid){
            record.changed(false);
        }
        return tbl;
    }
    return 0;
}

void FlatTable::copyTo(IlwisObject *obj){
    BaseTable::copyTo(obj);
}

std::vector<quint32> FlatTable::select(const QString &conditions) const
{
    return TableSelector::select(this, conditions);
}

bool FlatTable::initLoad(){
    if ( isDataLoaded())
        return true;

    bool ok = BaseTable::initLoad();

    for(int i=0; ok && i < columnCount() && _datagrid.size() > 0; ++i){
        QVariant var = cell(i,0);
        if ( !var.isValid()) {
            initValuesColumn(columndefinition(i).name());
        }
    }
    return ok;
}
<commit_msg>replaced recordCount() with datagrid.size()<commit_after>#include "kernel.h"
#include "ilwisdata.h"
#include "domain.h"
#include "range.h"
#include "datadefinition.h"
#include "columndefinition.h"
#include "connectorinterface.h"
#include "domainitem.h"
#include "basetable.h"
#include "flattable.h"
#include "tablemerger.h"
#include "itemrange.h"
#include "logicalexpressionparser.h"
#include "tableselector.h"

using namespace Ilwis;

FlatTable::FlatTable()
{
}

FlatTable::FlatTable(const Resource& resource) : BaseTable(resource){

}

FlatTable::~FlatTable()
{
    _datagrid.clear();
}

bool FlatTable::createTable()
{
    if(!BaseTable::createTable())
        return false;
    for(unsigned int i=0; i < recordCount(); ++i)
        _datagrid.push_back(std::vector<QVariant>(_columnDefinitionsByIndex.size()));
    return true;
}

quint32 FlatTable::newRecord()
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return iUNDEF;

    std::vector<QVariant> values;
    initRecord(values);
    record(NEW_RECORD, values);

    return recordCount() - 1;
}

void FlatTable::removeRecord(quint32 rec)
{
    if ( rec < recordCount()){
        _datagrid.erase(_datagrid.begin() + rec);
    }
}

bool FlatTable::prepare()
{
    return Table::prepare();
}

bool FlatTable::isValid() const
{
    return Table::isValid();
}

bool FlatTable::addColumn(const QString &name, const IDomain &domain)
{
    bool ok = BaseTable::addColumn(name, domain);
    if(!ok)
        return false;
    if ( isDataLoaded()){
        for(Record& row : _datagrid) {
            row.addColumn();
            row.changed(true);
        }
        initValuesColumn(name);
    }
    return true;

}

bool FlatTable::addColumn(const ColumnDefinition &def)
{
    bool ok = BaseTable::addColumn(def);
    if(!ok)
        return false;
    if (  isDataLoaded()) {
        for(Record& row : _datagrid) {
            row.addColumn();
            row.changed(true);
        }
        initValuesColumn(def.name());
    }
    return true;
}

std::vector<QVariant> FlatTable::column(quint32 index, quint32 start, quint32 stop) const {
    if (!const_cast<FlatTable *>(this)->initLoad())
        return std::vector<QVariant>();

    if ( !isColumnIndexValid(index))
        return std::vector<QVariant>();

    stop = std::min(stop, recordCount());
    start = std::max((quint32)0, start);
    std::vector<QVariant> data(stop - start);
    for(quint32 i=start; i < stop; ++i) {
        data[i - start] = _datagrid[i].cell(index);
    }
    return data;
}

std::vector<QVariant> FlatTable::column(const QString &nme, quint32 start, quint32 stop) const
{
    quint32 index = columnIndex(nme);
    return column(index, start, stop);

}

void FlatTable::column(quint32 index, const std::vector<QVariant> &vars, quint32 offset)
{
    if (index >= columnCount()) {
        ERROR2(ERR_ILLEGAL_VALUE_2,"Column index", name());
        return ;
    }
    column( _columnDefinitionsByIndex[index].name(), vars, offset);
}

void FlatTable::column(const QString &nme, const std::vector<QVariant> &vars, quint32 offset)
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( isReadOnly())
        return ;
    changed(true);

    quint32 index = columnIndex(nme);
    if ( !isColumnIndexValid(index))
        return ;

    quint32 rec = offset;
    _columnDefinitionsByIndex[index].changed(true);
    for(const QVariant& var : vars) {
        if ( rec < _datagrid.size()){
            _datagrid[rec].changed(true);
            _datagrid[rec++].cell(index, var);
        }
        else {
            _datagrid.push_back(std::vector<QVariant>(_columnDefinitionsByIndex.size()));
            _datagrid[rec].changed(true);
            _datagrid[rec++].cell(index,checkInput(var,index));
            recordCount(_datagrid.size());
        }
    }

}

const Record& FlatTable::record(quint32 rec) const{
    if (!const_cast<FlatTable *>(this)->initLoad())
        throw ErrorObject(QString(TR("failed load of table %1")).arg(name()));

    if ( rec < recordCount() && _datagrid.size() != 0) {
         return _datagrid[rec];
    }
    throw ErrorObject(QString("Requested record number is not in the table").arg(rec));
}

Record& FlatTable::recordRef(quint32 rec)
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        throw ErrorObject(QString(TR("failed load of table %1")).arg(name()));

    if ( rec < recordCount() && _datagrid.size() != 0) {
         return _datagrid[rec];
    }
    throw ErrorObject(QString("Requested record number is not in the table").arg(rec));
}

void FlatTable::record(quint32 rec, const std::vector<QVariant>& vars, quint32 offset)
{

    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( isReadOnly())
        return ;
    changed(true);
    if ( rec >= _datagrid.size() ) {
        _datagrid.push_back(std::vector<QVariant>(_columnDefinitionsByIndex.size()));
        _datagrid.back().changed(true);
        recordCount(_datagrid.size());
        rec = recordCount() - 1;
    }
    quint32 col = offset;
    int cols = std::min((quint32)vars.size() - offset, columnCount());
    for(const QVariant& var : vars) {
        if ( col < cols){
            _datagrid[rec].changed(true);
            _datagrid[rec].cell(col, checkInput(var, col));
            ++col;
        }
    }

}

QVariant FlatTable::cell(const QString& col, quint32 rec, bool asRaw) const {
    if (!const_cast<FlatTable *>(this)->initLoad())
        return QVariant();
    quint32 index = columnIndex(col);
    return cell(index , rec, asRaw);
}

QVariant FlatTable::cell(const quint32 index, quint32 rec, bool asRaw) const
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return QVariant();

    if ( !isColumnIndexValid(index))
        return QVariant();
    if ( rec < recordCount()) {
        QVariant var = _datagrid[rec].cell(index);
        if ( !asRaw) {
            ColumnDefinition coldef = columndefinition(index);
            return coldef.datadef().domain<>()->impliedValue(var);
        }
        return var;
    }
    kernel()->issues()->log(TR(ERR_INVALID_RECORD_SIZE_IN).arg(name()),IssueObject::itWarning);
    return QVariant();
}

void  FlatTable::setCell(quint32 index, quint32 rec, const QVariant& var){
    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( !isColumnIndexValid(index))
        return;

    if ( isReadOnly())
        return ;
    changed(true);

    _columnDefinitionsByIndex[index].changed(true);

    if ( rec >= recordCount()) {
        newRecord();
    }
    _datagrid[rec].cell(index, checkInput(var, index));
    _datagrid[rec].changed(true);

}

void FlatTable::setCell(const QString &col, quint32 rec, const QVariant &var)
{
    if (!const_cast<FlatTable *>(this)->initLoad())
        return ;

    if ( isReadOnly())
        return ;
    changed(true);

    quint32 index = columnIndex(col);
    setCell(index, rec, var);

}

IlwisTypes FlatTable::ilwisType() const
{
    return itFLATTABLE;
}

IlwisObject *FlatTable::clone()
{
    if (initLoad()){
        FlatTable *tbl = new FlatTable();
        copyTo(tbl);
        tbl->_datagrid = _datagrid;
        for(auto& record : tbl->_datagrid){
            record.changed(false);
        }
        return tbl;
    }
    return 0;
}

void FlatTable::copyTo(IlwisObject *obj){
    BaseTable::copyTo(obj);
}

std::vector<quint32> FlatTable::select(const QString &conditions) const
{
    return TableSelector::select(this, conditions);
}

bool FlatTable::initLoad(){
    if ( isDataLoaded())
        return true;

    bool ok = BaseTable::initLoad();

    for(int i=0; ok && i < columnCount() && _datagrid.size() > 0; ++i){
        QVariant var = cell(i,0);
        if ( !var.isValid()) {
            initValuesColumn(columndefinition(i).name());
        }
    }
    return ok;
}
<|endoftext|>


<commit_before>// Copyright (C) 2019-2020 European Spallation Source, see LICENSE file
//===----------------------------------------------------------------------===//
///
/// \file
///
/// \brief Digital geometry for SUMO (Sub-Modules) - implementation
///
//===----------------------------------------------------------------------===//

#include <jalousie/SumoMappings.h>
#include <fmt/format.h>
#include <jalousie/rapidcsv.h>

namespace Jalousie {

bool SumoCoordinates::is_valid() const {
  return ((wire_layer != kInvalidCoord) &&
      (wire != kInvalidCoord) &&
      (strip != kInvalidCoord));
}

std::string SumoCoordinates::debug() const {
  if (!is_valid())
    return "INV";
  return fmt::format("(wl{},w{},s{})", wire_layer, wire, strip);
}

SumoCoordinates min(const SumoCoordinates &a,
                                  const SumoCoordinates &b) {
  SumoCoordinates ret;
  ret.wire_layer = std::min(a.wire_layer, b.wire_layer);
  ret.wire = std::min(a.wire, b.wire);
  ret.strip = std::min(a.strip, b.strip);
  return ret;
}

SumoCoordinates max(const SumoCoordinates &a,
                                  const SumoCoordinates &b) {
  SumoCoordinates ret;
  ret.wire_layer = std::max(a.wire_layer, b.wire_layer);
  ret.wire = std::max(a.wire, b.wire);
  ret.strip = std::max(a.strip, b.strip);
  return ret;
}

SumoMappings::SumoMappings(std::string file_name, uint8_t sumo_id) {
  rapidcsv::Document doc(file_name,
                         rapidcsv::LabelParams(0, -1),
                         rapidcsv::SeparatorParams(';'));
  std::vector<int> line;
  SumoCoordinates coord;
  int anode;
  int cathode;
  for (size_t i = 0; i < doc.GetRowCount(); ++i) {
    line = doc.GetRow<int>(i);

    int sumo_type = line[0];
    if (sumo_type != sumo_id)
      continue;

    coord.wire_layer = line[1];
    coord.wire = line[2];
    coord.strip = line[3];
    anode = line[4];
    cathode = line[5];

    add_mapping(anode, cathode, coord);
  }
}

void SumoMappings::add_mapping(uint8_t anode, uint8_t cathode, SumoCoordinates coord) {
  if (!coord.is_valid())
    return;

  /// Initialize or update max coordinate
  if (table_.empty()) {
    min_ = coord;
    max_ = coord;
  }
  min_ = Jalousie::min(min_, coord);
  max_ = Jalousie::max(max_, coord);

  /// Resize table on demand
  if (table_.size() <= anode)
    table_.resize(anode + 1);
  auto &anode_line = table_[anode];
  if (anode_line.size() <= cathode)
    anode_line.resize(cathode + 1);

  /// Finally, assign
  anode_line[cathode] = coord;
}

SumoCoordinates SumoMappings::map(uint8_t anode, uint8_t cathode) const {
  if (table_.size() <= anode)
    return {};
  const auto &anode_line = table_[anode];
  if (anode_line.size() <= cathode)
    return {};
  return anode_line[cathode];
}

SumoCoordinates SumoMappings::min() const {
  return min_;
}

SumoCoordinates SumoMappings::max() const {
  return max_;
}

std::string SumoMappings::debug(bool depict_domain) const {
  std::string ret;
  ret += " --> [" + min_.debug() + " - " + max_.debug();
  if (!depict_domain)
    return ret;
  ret += "\n";
  for (size_t anode = 0; anode < table_.size(); ++anode) {
    const auto &anode_line = table_[anode];
    ret += fmt::format("{:<5}", anode);
    for (size_t cathode = 0; cathode < anode_line.size(); ++cathode) {
      ret += anode_line[cathode].is_valid() ? "@" : "-";
    }
    ret += "\n";
  }
  return ret;
}

}
<commit_msg>small corrections to doxygen headers<commit_after>// Copyright (C) 2019-2020 European Spallation Source, see LICENSE file
//===----------------------------------------------------------------------===//
///
/// \file
///
/// \brief Digital geometry for SUMO (SUper-MOdules) - implementation
///
//===----------------------------------------------------------------------===//

#include <jalousie/SumoMappings.h>
#include <fmt/format.h>
#include <jalousie/rapidcsv.h>

namespace Jalousie {

bool SumoCoordinates::is_valid() const {
  return ((wire_layer != kInvalidCoord) &&
      (wire != kInvalidCoord) &&
      (strip != kInvalidCoord));
}

std::string SumoCoordinates::debug() const {
  if (!is_valid())
    return "INV";
  return fmt::format("(wl{},w{},s{})", wire_layer, wire, strip);
}

SumoCoordinates min(const SumoCoordinates &a,
                                  const SumoCoordinates &b) {
  SumoCoordinates ret;
  ret.wire_layer = std::min(a.wire_layer, b.wire_layer);
  ret.wire = std::min(a.wire, b.wire);
  ret.strip = std::min(a.strip, b.strip);
  return ret;
}

SumoCoordinates max(const SumoCoordinates &a,
                                  const SumoCoordinates &b) {
  SumoCoordinates ret;
  ret.wire_layer = std::max(a.wire_layer, b.wire_layer);
  ret.wire = std::max(a.wire, b.wire);
  ret.strip = std::max(a.strip, b.strip);
  return ret;
}

SumoMappings::SumoMappings(std::string file_name, uint8_t sumo_id) {
  rapidcsv::Document doc(file_name,
                         rapidcsv::LabelParams(0, -1),
                         rapidcsv::SeparatorParams(';'));
  std::vector<int> line;
  SumoCoordinates coord;
  int anode;
  int cathode;
  for (size_t i = 0; i < doc.GetRowCount(); ++i) {
    line = doc.GetRow<int>(i);

    int sumo_type = line[0];
    if (sumo_type != sumo_id)
      continue;

    coord.wire_layer = line[1];
    coord.wire = line[2];
    coord.strip = line[3];
    anode = line[4];
    cathode = line[5];

    add_mapping(anode, cathode, coord);
  }
}

void SumoMappings::add_mapping(uint8_t anode, uint8_t cathode, SumoCoordinates coord) {
  if (!coord.is_valid())
    return;

  /// Initialize or update max coordinate
  if (table_.empty()) {
    min_ = coord;
    max_ = coord;
  }
  min_ = Jalousie::min(min_, coord);
  max_ = Jalousie::max(max_, coord);

  /// Resize table on demand
  if (table_.size() <= anode)
    table_.resize(anode + 1);
  auto &anode_line = table_[anode];
  if (anode_line.size() <= cathode)
    anode_line.resize(cathode + 1);

  /// Finally, assign
  anode_line[cathode] = coord;
}

SumoCoordinates SumoMappings::map(uint8_t anode, uint8_t cathode) const {
  if (table_.size() <= anode)
    return {};
  const auto &anode_line = table_[anode];
  if (anode_line.size() <= cathode)
    return {};
  return anode_line[cathode];
}

SumoCoordinates SumoMappings::min() const {
  return min_;
}

SumoCoordinates SumoMappings::max() const {
  return max_;
}

std::string SumoMappings::debug(bool depict_domain) const {
  std::string ret;
  ret += " --> [" + min_.debug() + " - " + max_.debug();
  if (!depict_domain)
    return ret;
  ret += "\n";
  for (size_t anode = 0; anode < table_.size(); ++anode) {
    const auto &anode_line = table_[anode];
    ret += fmt::format("{:<5}", anode);
    for (size_t cathode = 0; cathode < anode_line.size(); ++cathode) {
      ret += anode_line[cathode].is_valid() ? "@" : "-";
    }
    ret += "\n";
  }
  return ret;
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"

#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#elif defined(OS_POSIX)
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#endif
#if defined(OS_LINUX)
#include <sys/prctl.h>
#endif

#include <algorithm>

#include "base/file_path.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_piece.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"

#if defined(OS_LINUX)
// Linux/glibc doesn't natively have setproctitle().
#include "base/setproctitle_linux.h"
#endif

CommandLine* CommandLine::current_process_commandline_ = NULL;

// Since we use a lazy match, make sure that longer versions (like L"--")
// are listed before shorter versions (like L"-") of similar prefixes.
#if defined(OS_WIN)
const wchar_t* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
const wchar_t kSwitchTerminator[] = L"--";
const wchar_t kSwitchValueSeparator[] = L"=";
#elif defined(OS_POSIX)
// Unixes don't use slash as a switch.
const char* const kSwitchPrefixes[] = {"--", "-"};
const char kSwitchTerminator[] = "--";
const char kSwitchValueSeparator[] = "=";
#endif

#if defined(OS_WIN)
// Lowercase a string.  This is used to lowercase switch names.
// Is this what we really want?  It seems crazy to me.  I've left it in
// for backwards compatibility on Windows.
static void Lowercase(std::string* parameter) {
  transform(parameter->begin(), parameter->end(), parameter->begin(),
            tolower);
}
#endif

#if defined(OS_WIN)
CommandLine::CommandLine(ArgumentsOnly args_only) {
}

void CommandLine::ParseFromString(const std::wstring& command_line) {
  TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);

  if (command_line_string_.empty())
    return;

  int num_args = 0;
  wchar_t** args = NULL;

  args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);

  // Populate program_ with the trimmed version of the first arg.
  TrimWhitespace(args[0], TRIM_ALL, &program_);

  bool parse_switches = true;
  for (int i = 1; i < num_args; ++i) {
    std::wstring arg;
    TrimWhitespace(args[i], TRIM_ALL, &arg);

    if (!parse_switches) {
      loose_values_.push_back(arg);
      continue;
    }

    if (arg == kSwitchTerminator) {
      parse_switches = false;
      continue;
    }

    std::string switch_string;
    std::wstring switch_value;
    if (IsSwitch(arg, &switch_string, &switch_value)) {
      switches_[switch_string] = switch_value;
    } else {
      loose_values_.push_back(arg);
    }
  }

  if (args)
    LocalFree(args);
}

CommandLine::CommandLine(const FilePath& program) {
  if (!program.empty()) {
    program_ = program.value();
    command_line_string_ = L'"' + program.value() + L'"';
  }
}

#elif defined(OS_POSIX)
CommandLine::CommandLine(ArgumentsOnly args_only) {
  // Push an empty argument, because we always assume argv_[0] is a program.
  argv_.push_back("");
}

void CommandLine::InitFromArgv(int argc, const char* const* argv) {
  for (int i = 0; i < argc; ++i)
    argv_.push_back(argv[i]);
  InitFromArgv(argv_);
}

void CommandLine::InitFromArgv(const std::vector<std::string>& argv) {
  argv_ = argv;
  bool parse_switches = true;
  for (size_t i = 1; i < argv_.size(); ++i) {
    const std::string& arg = argv_[i];

    if (!parse_switches) {
      loose_values_.push_back(arg);
      continue;
    }

    if (arg == kSwitchTerminator) {
      parse_switches = false;
      continue;
    }

    std::string switch_string;
    std::string switch_value;
    if (IsSwitch(arg, &switch_string, &switch_value)) {
      switches_[switch_string] = switch_value;
    } else {
      loose_values_.push_back(arg);
    }
  }
}

CommandLine::CommandLine(const FilePath& program) {
  argv_.push_back(program.value());
}

#endif

// static
bool CommandLine::IsSwitch(const StringType& parameter_string,
                           std::string* switch_string,
                           StringType* switch_value) {
  switch_string->clear();
  switch_value->clear();

  for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
    StringType prefix(kSwitchPrefixes[i]);
    if (parameter_string.find(prefix) != 0)
      continue;

    const size_t switch_start = prefix.length();
    const size_t equals_position = parameter_string.find(
        kSwitchValueSeparator, switch_start);
    StringType switch_native;
    if (equals_position == StringType::npos) {
      switch_native = parameter_string.substr(switch_start);
    } else {
      switch_native = parameter_string.substr(
          switch_start, equals_position - switch_start);
      *switch_value = parameter_string.substr(equals_position + 1);
    }
#if defined(OS_WIN)
    *switch_string = WideToASCII(switch_native);
    Lowercase(switch_string);
#else
    *switch_string = switch_native;
#endif

    return true;
  }

  return false;
}

// static
void CommandLine::Init(int argc, const char* const* argv) {
  delete current_process_commandline_;
  current_process_commandline_ = new CommandLine;
#if defined(OS_WIN)
  current_process_commandline_->ParseFromString(::GetCommandLineW());
#elif defined(OS_POSIX)
  current_process_commandline_->InitFromArgv(argc, argv);
#endif

#if defined(OS_LINUX)
  if (argv)
    setproctitle_init(const_cast<char**>(argv));
#endif
}

#if defined(OS_POSIX) && !defined(OS_MACOSX)
// static
void CommandLine::SetProcTitle() {
  // Build a single string which consists of all the arguments separated
  // by spaces. We can't actually keep them separate due to the way the
  // setproctitle() function works.
  std::string title;
  bool have_argv0 = false;
#if defined(OS_LINUX)
  // In Linux we sometimes exec ourselves from /proc/self/exe, but this makes us
  // show up as "exe" in process listings. Read the symlink /proc/self/exe and
  // use the path it points at for our process title. Note that this is only for
  // display purposes and has no TOCTTOU security implications.
  char buffer[PATH_MAX];
  // Note: readlink() does not append a null byte to terminate the string.
  ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
  DCHECK(length <= static_cast<ssize_t>(sizeof(buffer)));
  if (length > 0) {
    have_argv0 = true;
    title.assign(buffer, length);
    // If the binary has since been deleted, Linux appends " (deleted)" to the
    // symlink target. Remove it, since this is not really part of our name.
    const std::string kDeletedSuffix = " (deleted)";
    if (EndsWith(title, kDeletedSuffix, true))
      title.resize(title.size() - kDeletedSuffix.size());
#if defined(PR_SET_NAME)
    // If PR_SET_NAME is available at compile time, we try using it. We ignore
    // any errors if the kernel does not support it at runtime though. When
    // available, this lets us set the short process name that shows when the
    // full command line is not being displayed in most process listings.
    prctl(PR_SET_NAME, FilePath(title).BaseName().value().c_str());
#endif
  }
#endif
  for (size_t i = 1; i < current_process_commandline_->argv_.size(); ++i) {
    if (!title.empty())
      title += " ";
    title += current_process_commandline_->argv_[i];
  }
  // Disable prepending argv[0] with '-' if we prepended it ourselves above.
  setproctitle(have_argv0 ? "-%s" : "%s", title.c_str());
}
#endif

void CommandLine::Reset() {
  DCHECK(current_process_commandline_ != NULL);
  delete current_process_commandline_;
  current_process_commandline_ = NULL;
}

bool CommandLine::HasSwitch(const std::string& switch_string) const {
  std::string lowercased_switch(switch_string);
#if defined(OS_WIN)
  Lowercase(&lowercased_switch);
#endif
  return switches_.find(lowercased_switch) != switches_.end();
}

std::wstring CommandLine::GetSwitchValue(
    const std::string& switch_string) const {
  std::string lowercased_switch(switch_string);
#if defined(OS_WIN)
  Lowercase(&lowercased_switch);
#endif

  std::map<std::string, StringType>::const_iterator result =
      switches_.find(lowercased_switch);

  if (result == switches_.end()) {
    return L"";
  } else {
#if defined(OS_WIN)
    return result->second;
#else
    return base::SysNativeMBToWide(result->second);
#endif
  }
}

#if defined(OS_WIN)
std::vector<std::wstring> CommandLine::GetLooseValues() const {
  return loose_values_;
}
std::wstring CommandLine::program() const {
  return program_;
}
#else
std::vector<std::wstring> CommandLine::GetLooseValues() const {
  std::vector<std::wstring> values;
  for (size_t i = 0; i < loose_values_.size(); ++i)
    values.push_back(base::SysNativeMBToWide(loose_values_[i]));
  return values;
}
std::wstring CommandLine::program() const {
  DCHECK_GT(argv_.size(), 0U);
  return base::SysNativeMBToWide(argv_[0]);
}
#endif

// static
std::wstring CommandLine::PrefixedSwitchString(
    const std::string& switch_string) {
#if defined(OS_WIN)
  return kSwitchPrefixes[0] + ASCIIToWide(switch_string);
#else
  return ASCIIToWide(kSwitchPrefixes[0] + switch_string);
#endif
}

// static
std::wstring CommandLine::PrefixedSwitchStringWithValue(
    const std::string& switch_string, const std::wstring& value_string) {
  if (value_string.empty()) {
    return PrefixedSwitchString(switch_string);
  }

  return PrefixedSwitchString(switch_string +
#if defined(OS_WIN)
                              WideToASCII(kSwitchValueSeparator)
#else
                              kSwitchValueSeparator
#endif
                              ) + value_string;
}

#if defined(OS_WIN)
void CommandLine::AppendSwitch(const std::string& switch_string) {
  std::wstring prefixed_switch_string = PrefixedSwitchString(switch_string);
  command_line_string_.append(L" ");
  command_line_string_.append(prefixed_switch_string);
  switches_[switch_string] = L"";
}

void CommandLine::AppendSwitchWithValue(const std::string& switch_string,
                                        const std::wstring& value_string) {
  std::wstring value_string_edit;

  // NOTE(jhughes): If the value contains a quotation mark at one
  //                end but not both, you may get unusable output.
  if (!value_string.empty() &&
      (value_string.find(L" ") != std::wstring::npos) &&
      (value_string[0] != L'"') &&
      (value_string[value_string.length() - 1] != L'"')) {
    // need to provide quotes
    value_string_edit = StringPrintf(L"\"%ls\"", value_string.c_str());
  } else {
    value_string_edit = value_string;
  }

  std::wstring combined_switch_string =
      PrefixedSwitchStringWithValue(switch_string, value_string_edit);

  command_line_string_.append(L" ");
  command_line_string_.append(combined_switch_string);

  switches_[switch_string] = value_string;
}

void CommandLine::AppendLooseValue(const std::wstring& value) {
  // TODO(evan): quoting?
  command_line_string_.append(L" ");
  command_line_string_.append(value);
  loose_values_.push_back(value);
}

void CommandLine::AppendArguments(const CommandLine& other,
                                  bool include_program) {
  // Verify include_program is used correctly.
  // Logic could be shorter but this is clearer.
  DCHECK(include_program ? !other.program().empty() : other.program().empty());
  command_line_string_ += L" " + other.command_line_string_;
  std::map<std::string, StringType>::const_iterator i;
  for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
    switches_[i->first] = i->second;
}

void CommandLine::PrependWrapper(const std::wstring& wrapper) {
  // The wrapper may have embedded arguments (like "gdb --args"). In this case,
  // we don't pretend to do anything fancy, we just split on spaces.
  std::vector<std::wstring> wrapper_and_args;
  SplitString(wrapper, ' ', &wrapper_and_args);
  program_ = wrapper_and_args[0];
  command_line_string_ = wrapper + L" " + command_line_string_;
}

#elif defined(OS_POSIX)
void CommandLine::AppendSwitch(const std::string& switch_string) {
  argv_.push_back(kSwitchPrefixes[0] + switch_string);
  switches_[switch_string] = "";
}

void CommandLine::AppendSwitchWithValue(const std::string& switch_string,
                                        const std::wstring& value_string) {
  std::string mb_value = base::SysWideToNativeMB(value_string);

  argv_.push_back(kSwitchPrefixes[0] + switch_string +
                  kSwitchValueSeparator + mb_value);
  switches_[switch_string] = mb_value;
}

void CommandLine::AppendLooseValue(const std::wstring& value) {
  argv_.push_back(base::SysWideToNativeMB(value));
}

void CommandLine::AppendArguments(const CommandLine& other,
                                  bool include_program) {
  // Verify include_program is used correctly.
  // Logic could be shorter but this is clearer.
  DCHECK(include_program ? !other.program().empty() : other.program().empty());

  size_t first_arg = include_program ? 0 : 1;
  for (size_t i = first_arg; i < other.argv_.size(); ++i)
    argv_.push_back(other.argv_[i]);
  std::map<std::string, StringType>::const_iterator i;
  for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
    switches_[i->first] = i->second;
}

void CommandLine::PrependWrapper(const std::wstring& wrapper_wide) {
  // The wrapper may have embedded arguments (like "gdb --args"). In this case,
  // we don't pretend to do anything fancy, we just split on spaces.
  const std::string wrapper = base::SysWideToNativeMB(wrapper_wide);
  std::vector<std::string> wrapper_and_args;
  SplitString(wrapper, ' ', &wrapper_and_args);
  argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
}

#endif
<commit_msg>Cleanup: Replace deprecated CommandLine::program() with CommandLine::GetProgram(). Simplify a couple DCHECKs with DCHECK_EQ.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"

#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#elif defined(OS_POSIX)
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#endif
#if defined(OS_LINUX)
#include <sys/prctl.h>
#endif

#include <algorithm>

#include "base/file_path.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_piece.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"

#if defined(OS_LINUX)
// Linux/glibc doesn't natively have setproctitle().
#include "base/setproctitle_linux.h"
#endif

CommandLine* CommandLine::current_process_commandline_ = NULL;

// Since we use a lazy match, make sure that longer versions (like L"--")
// are listed before shorter versions (like L"-") of similar prefixes.
#if defined(OS_WIN)
const wchar_t* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
const wchar_t kSwitchTerminator[] = L"--";
const wchar_t kSwitchValueSeparator[] = L"=";
#elif defined(OS_POSIX)
// Unixes don't use slash as a switch.
const char* const kSwitchPrefixes[] = {"--", "-"};
const char kSwitchTerminator[] = "--";
const char kSwitchValueSeparator[] = "=";
#endif

#if defined(OS_WIN)
// Lowercase a string.  This is used to lowercase switch names.
// Is this what we really want?  It seems crazy to me.  I've left it in
// for backwards compatibility on Windows.
static void Lowercase(std::string* parameter) {
  transform(parameter->begin(), parameter->end(), parameter->begin(),
            tolower);
}
#endif

#if defined(OS_WIN)
CommandLine::CommandLine(ArgumentsOnly args_only) {
}

void CommandLine::ParseFromString(const std::wstring& command_line) {
  TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);

  if (command_line_string_.empty())
    return;

  int num_args = 0;
  wchar_t** args = NULL;

  args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);

  // Populate program_ with the trimmed version of the first arg.
  TrimWhitespace(args[0], TRIM_ALL, &program_);

  bool parse_switches = true;
  for (int i = 1; i < num_args; ++i) {
    std::wstring arg;
    TrimWhitespace(args[i], TRIM_ALL, &arg);

    if (!parse_switches) {
      loose_values_.push_back(arg);
      continue;
    }

    if (arg == kSwitchTerminator) {
      parse_switches = false;
      continue;
    }

    std::string switch_string;
    std::wstring switch_value;
    if (IsSwitch(arg, &switch_string, &switch_value)) {
      switches_[switch_string] = switch_value;
    } else {
      loose_values_.push_back(arg);
    }
  }

  if (args)
    LocalFree(args);
}

CommandLine::CommandLine(const FilePath& program) {
  if (!program.empty()) {
    program_ = program.value();
    command_line_string_ = L'"' + program.value() + L'"';
  }
}

#elif defined(OS_POSIX)
CommandLine::CommandLine(ArgumentsOnly args_only) {
  // Push an empty argument, because we always assume argv_[0] is a program.
  argv_.push_back("");
}

void CommandLine::InitFromArgv(int argc, const char* const* argv) {
  for (int i = 0; i < argc; ++i)
    argv_.push_back(argv[i]);
  InitFromArgv(argv_);
}

void CommandLine::InitFromArgv(const std::vector<std::string>& argv) {
  argv_ = argv;
  bool parse_switches = true;
  for (size_t i = 1; i < argv_.size(); ++i) {
    const std::string& arg = argv_[i];

    if (!parse_switches) {
      loose_values_.push_back(arg);
      continue;
    }

    if (arg == kSwitchTerminator) {
      parse_switches = false;
      continue;
    }

    std::string switch_string;
    std::string switch_value;
    if (IsSwitch(arg, &switch_string, &switch_value)) {
      switches_[switch_string] = switch_value;
    } else {
      loose_values_.push_back(arg);
    }
  }
}

CommandLine::CommandLine(const FilePath& program) {
  argv_.push_back(program.value());
}

#endif

// static
bool CommandLine::IsSwitch(const StringType& parameter_string,
                           std::string* switch_string,
                           StringType* switch_value) {
  switch_string->clear();
  switch_value->clear();

  for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
    StringType prefix(kSwitchPrefixes[i]);
    if (parameter_string.find(prefix) != 0)
      continue;

    const size_t switch_start = prefix.length();
    const size_t equals_position = parameter_string.find(
        kSwitchValueSeparator, switch_start);
    StringType switch_native;
    if (equals_position == StringType::npos) {
      switch_native = parameter_string.substr(switch_start);
    } else {
      switch_native = parameter_string.substr(
          switch_start, equals_position - switch_start);
      *switch_value = parameter_string.substr(equals_position + 1);
    }
#if defined(OS_WIN)
    *switch_string = WideToASCII(switch_native);
    Lowercase(switch_string);
#else
    *switch_string = switch_native;
#endif

    return true;
  }

  return false;
}

// static
void CommandLine::Init(int argc, const char* const* argv) {
  delete current_process_commandline_;
  current_process_commandline_ = new CommandLine;
#if defined(OS_WIN)
  current_process_commandline_->ParseFromString(::GetCommandLineW());
#elif defined(OS_POSIX)
  current_process_commandline_->InitFromArgv(argc, argv);
#endif

#if defined(OS_LINUX)
  if (argv)
    setproctitle_init(const_cast<char**>(argv));
#endif
}

#if defined(OS_POSIX) && !defined(OS_MACOSX)
// static
void CommandLine::SetProcTitle() {
  // Build a single string which consists of all the arguments separated
  // by spaces. We can't actually keep them separate due to the way the
  // setproctitle() function works.
  std::string title;
  bool have_argv0 = false;
#if defined(OS_LINUX)
  // In Linux we sometimes exec ourselves from /proc/self/exe, but this makes us
  // show up as "exe" in process listings. Read the symlink /proc/self/exe and
  // use the path it points at for our process title. Note that this is only for
  // display purposes and has no TOCTTOU security implications.
  char buffer[PATH_MAX];
  // Note: readlink() does not append a null byte to terminate the string.
  ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
  DCHECK(length <= static_cast<ssize_t>(sizeof(buffer)));
  if (length > 0) {
    have_argv0 = true;
    title.assign(buffer, length);
    // If the binary has since been deleted, Linux appends " (deleted)" to the
    // symlink target. Remove it, since this is not really part of our name.
    const std::string kDeletedSuffix = " (deleted)";
    if (EndsWith(title, kDeletedSuffix, true))
      title.resize(title.size() - kDeletedSuffix.size());
#if defined(PR_SET_NAME)
    // If PR_SET_NAME is available at compile time, we try using it. We ignore
    // any errors if the kernel does not support it at runtime though. When
    // available, this lets us set the short process name that shows when the
    // full command line is not being displayed in most process listings.
    prctl(PR_SET_NAME, FilePath(title).BaseName().value().c_str());
#endif
  }
#endif
  for (size_t i = 1; i < current_process_commandline_->argv_.size(); ++i) {
    if (!title.empty())
      title += " ";
    title += current_process_commandline_->argv_[i];
  }
  // Disable prepending argv[0] with '-' if we prepended it ourselves above.
  setproctitle(have_argv0 ? "-%s" : "%s", title.c_str());
}
#endif

void CommandLine::Reset() {
  DCHECK(current_process_commandline_ != NULL);
  delete current_process_commandline_;
  current_process_commandline_ = NULL;
}

bool CommandLine::HasSwitch(const std::string& switch_string) const {
  std::string lowercased_switch(switch_string);
#if defined(OS_WIN)
  Lowercase(&lowercased_switch);
#endif
  return switches_.find(lowercased_switch) != switches_.end();
}

std::wstring CommandLine::GetSwitchValue(
    const std::string& switch_string) const {
  std::string lowercased_switch(switch_string);
#if defined(OS_WIN)
  Lowercase(&lowercased_switch);
#endif

  std::map<std::string, StringType>::const_iterator result =
      switches_.find(lowercased_switch);

  if (result == switches_.end()) {
    return L"";
  } else {
#if defined(OS_WIN)
    return result->second;
#else
    return base::SysNativeMBToWide(result->second);
#endif
  }
}

#if defined(OS_WIN)
std::vector<std::wstring> CommandLine::GetLooseValues() const {
  return loose_values_;
}
std::wstring CommandLine::program() const {
  return program_;
}
#else
std::vector<std::wstring> CommandLine::GetLooseValues() const {
  std::vector<std::wstring> values;
  for (size_t i = 0; i < loose_values_.size(); ++i)
    values.push_back(base::SysNativeMBToWide(loose_values_[i]));
  return values;
}
std::wstring CommandLine::program() const {
  DCHECK_GT(argv_.size(), 0U);
  return base::SysNativeMBToWide(argv_[0]);
}
#endif

// static
std::wstring CommandLine::PrefixedSwitchString(
    const std::string& switch_string) {
#if defined(OS_WIN)
  return kSwitchPrefixes[0] + ASCIIToWide(switch_string);
#else
  return ASCIIToWide(kSwitchPrefixes[0] + switch_string);
#endif
}

// static
std::wstring CommandLine::PrefixedSwitchStringWithValue(
    const std::string& switch_string, const std::wstring& value_string) {
  if (value_string.empty()) {
    return PrefixedSwitchString(switch_string);
  }

  return PrefixedSwitchString(switch_string +
#if defined(OS_WIN)
                              WideToASCII(kSwitchValueSeparator)
#else
                              kSwitchValueSeparator
#endif
                              ) + value_string;
}

#if defined(OS_WIN)
void CommandLine::AppendSwitch(const std::string& switch_string) {
  std::wstring prefixed_switch_string = PrefixedSwitchString(switch_string);
  command_line_string_.append(L" ");
  command_line_string_.append(prefixed_switch_string);
  switches_[switch_string] = L"";
}

void CommandLine::AppendSwitchWithValue(const std::string& switch_string,
                                        const std::wstring& value_string) {
  std::wstring value_string_edit;

  // NOTE(jhughes): If the value contains a quotation mark at one
  //                end but not both, you may get unusable output.
  if (!value_string.empty() &&
      (value_string.find(L" ") != std::wstring::npos) &&
      (value_string[0] != L'"') &&
      (value_string[value_string.length() - 1] != L'"')) {
    // need to provide quotes
    value_string_edit = StringPrintf(L"\"%ls\"", value_string.c_str());
  } else {
    value_string_edit = value_string;
  }

  std::wstring combined_switch_string =
      PrefixedSwitchStringWithValue(switch_string, value_string_edit);

  command_line_string_.append(L" ");
  command_line_string_.append(combined_switch_string);

  switches_[switch_string] = value_string;
}

void CommandLine::AppendLooseValue(const std::wstring& value) {
  // TODO(evan): quoting?
  command_line_string_.append(L" ");
  command_line_string_.append(value);
  loose_values_.push_back(value);
}

void CommandLine::AppendArguments(const CommandLine& other,
                                  bool include_program) {
  // Verify include_program is used correctly.
  // Logic could be shorter but this is clearer.
  DCHECK_EQ(include_program, !other.GetProgram().empty());
  command_line_string_ += L" " + other.command_line_string_;
  std::map<std::string, StringType>::const_iterator i;
  for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
    switches_[i->first] = i->second;
}

void CommandLine::PrependWrapper(const std::wstring& wrapper) {
  // The wrapper may have embedded arguments (like "gdb --args"). In this case,
  // we don't pretend to do anything fancy, we just split on spaces.
  std::vector<std::wstring> wrapper_and_args;
  SplitString(wrapper, ' ', &wrapper_and_args);
  program_ = wrapper_and_args[0];
  command_line_string_ = wrapper + L" " + command_line_string_;
}

#elif defined(OS_POSIX)
void CommandLine::AppendSwitch(const std::string& switch_string) {
  argv_.push_back(kSwitchPrefixes[0] + switch_string);
  switches_[switch_string] = "";
}

void CommandLine::AppendSwitchWithValue(const std::string& switch_string,
                                        const std::wstring& value_string) {
  std::string mb_value = base::SysWideToNativeMB(value_string);

  argv_.push_back(kSwitchPrefixes[0] + switch_string +
                  kSwitchValueSeparator + mb_value);
  switches_[switch_string] = mb_value;
}

void CommandLine::AppendLooseValue(const std::wstring& value) {
  argv_.push_back(base::SysWideToNativeMB(value));
}

void CommandLine::AppendArguments(const CommandLine& other,
                                  bool include_program) {
  // Verify include_program is used correctly.
  // Logic could be shorter but this is clearer.
  DCHECK_EQ(include_program, !other.GetProgram().empty());
  size_t first_arg = include_program ? 0 : 1;
  for (size_t i = first_arg; i < other.argv_.size(); ++i)
    argv_.push_back(other.argv_[i]);
  std::map<std::string, StringType>::const_iterator i;
  for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
    switches_[i->first] = i->second;
}

void CommandLine::PrependWrapper(const std::wstring& wrapper_wide) {
  // The wrapper may have embedded arguments (like "gdb --args"). In this case,
  // we don't pretend to do anything fancy, we just split on spaces.
  const std::string wrapper = base::SysWideToNativeMB(wrapper_wide);
  std::vector<std::string> wrapper_and_args;
  SplitString(wrapper, ' ', &wrapper_and_args);
  argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
}

#endif
<|endoftext|>


<commit_before><commit_msg>Revert 35907 - Fixes CommandLine::AppendLooseValue() to append the parameter to the loose_values_ vector.<commit_after><|endoftext|>


<commit_before>/*VRP*********************************************************************
 *
 * vehicle routing problems
 *      A collection of C++ classes for developing VRP solutions
 *      and specific solutions developed using these classes.
 *
 * Copyright 2014 Stephen Woodbridge <woodbri@imaptools.com>
 * Copyright 2014 Vicky Vergara <vicky_vergara@hotmail.com>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the MIT License. Please file LICENSE for details.
 *
 ********************************************************************VRP*/

#include <iostream>
#include "move.h"

/*! \fn bool Move::operator==(const Move &rhs) const
 * \brief Compare two moves and report if they are equal
 */
bool Move::operator==(const Move &rhs) const {
    return nid1==rhs.nid1 and nid2==rhs.nid2 and
           vid1==rhs.vid1 and vid2==rhs.vid2 and
           pos1==rhs.pos1 and pos2==rhs.pos2;
}

/*! \fn bool Move::less(const Move& m) const
 * \brief Compare two moves and report if move \< rhs.move
 *
 * This less than comparision operator is used by the TabuList map function
 * for ordering the moves in the container.
 */
bool Move::less(const Move& m) const {
    return nid1<m.nid1 or ( nid1==m.nid1 and
            ( nid2<m.nid2 or ( nid2==m.nid2 and
              ( vid1<m.vid1 or ( vid1==m.vid1 and
                ( pos1<m.pos1 or ( pos1==m.pos1 and pos2<m.pos2 )))))));
}

/*! \fn bool Move::isForbidden(const Move &tabu) const
 * \brief Check if a given move is forbidden based on the TabuList
 *
 * The isForbidden() test is not associative ( ie: A.equiv(B) != B.equiv(A) ).
 * This test is used to determine if A would be tabu if B is on the tabu list
 *
 * - prohibition rules for Ins
 *   - Rule PR5 - move removing any order from tabu.vid2.
 *     This rule basically says if we remove a node from vid2
 *     then we are not allowed to add a node back to vid2 until
 *     the tabu length expires.
 *     This rule is to promote the elimiation of vehicles
 *
 * - prohibition rules for IntraSw
 *   - This rules says that if we have swapped either the source
 *     or the destination nodes that they can not be moved again
 *     until the tabu length expires.
 *
 * - prohibition rules for InterSw
 *   - This rules says that if we have swapped either the source
 *     or the destination nodes that they can not be moved again
 *     until the tabu length expires.
 */
bool Move::isForbidden(const Move &tabu) const {
    if (*this == tabu) return true;

    if (mtype == Ins) {
        if (vid1 == tabu.vid2) return true;
    }
    else if (mtype == IntraSw) {
        if (nid1==tabu.nid1 or nid2==tabu.nid2 or
            nid1==tabu.nid2 or nid2==tabu.nid1 ) return true;
    }
    else {
        if (nid1==tabu.nid1 or nid2==tabu.nid2 or
            nid1==tabu.nid2 or nid2==tabu.nid1 ) return true;
    }
    return false;
}

/*! \fn void Move::dump() const
 * \brief Print the move.
 */
void Move::dump() const {
    std::cout << "Move: " << mtype
              << ",\t" << nid1
              << ",\t" << nid2
              << ",\t" << vid1
              << ",\t" << vid2
              << ",\t" << pos1
              << ",\t" << pos2
              << ",\t" << savings
              << std::endl;
}

void Move::Dump() const {
    switch (mtype){
    case Ins:
    	std::cout << "Move: INS"
              << "\t    NodeID:" << nid1
              << "\tFrom Truck:" << vid1
              << "\t  From Pos:" << pos1
              << "\t  To Truck:" << vid2
              << "\t    To Pos:" << pos2
              << "\t   savings:" << savings
              << std::endl;
    	break;
    case IntraSw:
        std::cout << "Move: IntraSw"
              << "\t    NodeID:" << nid1
              << "\t  At Truck:" << vid1
              << "\t  From Pos:" << pos1
              << "\t    To Pos:" << pos2
              << "\t   savings:" << savings
              << std::endl;
        break;
    case InterSw:
        std::cout << "Move: InterSw"
              << "\t    NodeID:" << nid1
              << "\t  (at Truck:" << vid1
              << "\t  at Pos:" << pos1
              << ")\t with NodeID:" << nid2
              << "\t    (at Truck:" << vid2
              << "\t      at Pos:" << pos2
              << ")\t   savings:" << savings
              << std::endl;
        break;
    }

}

<commit_msg>Fix a nasty bug in Move::isForbidden where from and to trucks were reversed.<commit_after>/*VRP*********************************************************************
 *
 * vehicle routing problems
 *      A collection of C++ classes for developing VRP solutions
 *      and specific solutions developed using these classes.
 *
 * Copyright 2014 Stephen Woodbridge <woodbri@imaptools.com>
 * Copyright 2014 Vicky Vergara <vicky_vergara@hotmail.com>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the MIT License. Please file LICENSE for details.
 *
 ********************************************************************VRP*/

#include <iostream>
#include "move.h"

/*! \fn bool Move::operator==(const Move &rhs) const
 * \brief Compare two moves and report if they are equal
 */
bool Move::operator==(const Move &rhs) const {
    return nid1==rhs.nid1 and nid2==rhs.nid2 and
           vid1==rhs.vid1 and vid2==rhs.vid2 and
           pos1==rhs.pos1 and pos2==rhs.pos2;
}

/*! \fn bool Move::less(const Move& m) const
 * \brief Compare two moves and report if move \< rhs.move
 *
 * This less than comparision operator is used by the TabuList map function
 * for ordering the moves in the container.
 */
bool Move::less(const Move& m) const {
    return nid1<m.nid1 or ( nid1==m.nid1 and
            ( nid2<m.nid2 or ( nid2==m.nid2 and
              ( vid1<m.vid1 or ( vid1==m.vid1 and
                ( pos1<m.pos1 or ( pos1==m.pos1 and pos2<m.pos2 )))))));
}

/*! \fn bool Move::isForbidden(const Move &tabu) const
 * \brief Check if a given move is forbidden based on the TabuList
 *
 * The isForbidden() test is not associative ( ie: A.equiv(B) != B.equiv(A) ).
 * This test is used to determine if A would be tabu if B is on the tabu list
 *
 * - prohibition rules for Ins
 *   - Rule PR5 - move removing any order from tabu.vid1.
 *     This rule basically says if we remove a node from vid1
 *     then we are not allowed to add a node back to vid1 until
 *     the tabu length expires.
 *     This rule is to promote the elimiation of vehicles
 *
 * - prohibition rules for IntraSw
 *   - This rules says that if we have swapped either the source
 *     or the destination nodes that they can not be moved again
 *     until the tabu length expires.
 *
 * - prohibition rules for InterSw
 *   - This rules says that if we have swapped either the source
 *     or the destination nodes that they can not be moved again
 *     until the tabu length expires.
 */
bool Move::isForbidden(const Move &tabu) const {
    if (*this == tabu) return true;

    if (mtype == Ins) {
        if (vid2 == tabu.vid1) return true;
    }
    else if (mtype == IntraSw) {
        if (nid1==tabu.nid1 or nid2==tabu.nid2 or
            nid1==tabu.nid2 or nid2==tabu.nid1 ) return true;
    }
    else {
        if (nid1==tabu.nid1 or nid2==tabu.nid2 or
            nid1==tabu.nid2 or nid2==tabu.nid1 ) return true;
    }
    return false;
}

/*! \fn void Move::dump() const
 * \brief Print the move.
 */
void Move::dump() const {
    std::cout << "Move: " << mtype
              << ",\t" << nid1
              << ",\t" << nid2
              << ",\t" << vid1
              << ",\t" << vid2
              << ",\t" << pos1
              << ",\t" << pos2
              << ",\t" << savings
              << std::endl;
}

void Move::Dump() const {
    switch (mtype){
    case Ins:
    	std::cout << "Move: INS"
              << "\t    NodeID:" << nid1
              << "\tFrom Truck:" << vid1
              << "\t  From Pos:" << pos1
              << "\t  To Truck:" << vid2
              << "\t    To Pos:" << pos2
              << "\t   savings:" << savings
              << std::endl;
    	break;
    case IntraSw:
        std::cout << "Move: IntraSw"
              << "\t    NodeID:" << nid1
              << "\t  At Truck:" << vid1
              << "\t  From Pos:" << pos1
              << "\t    To Pos:" << pos2
              << "\t   savings:" << savings
              << std::endl;
        break;
    case InterSw:
        std::cout << "Move: InterSw"
              << "\t    NodeID:" << nid1
              << "\t  (at Truck:" << vid1
              << "\t  at Pos:" << pos1
              << ")\t with NodeID:" << nid2
              << "\t    (at Truck:" << vid2
              << "\t      at Pos:" << pos2
              << ")\t   savings:" << savings
              << std::endl;
        break;
    }

}

<|endoftext|>