summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib')
-rw-r--r--src/lib/netlist/plib/gmres.h450
-rw-r--r--src/lib/netlist/plib/mat_cr.h530
-rw-r--r--src/lib/netlist/plib/palloc.cpp105
-rw-r--r--src/lib/netlist/plib/palloc.h513
-rw-r--r--src/lib/netlist/plib/parray.h126
-rw-r--r--src/lib/netlist/plib/pchrono.cpp4
-rw-r--r--src/lib/netlist/plib/pchrono.h52
-rw-r--r--src/lib/netlist/plib/pconfig.h51
-rw-r--r--src/lib/netlist/plib/pdynlib.cpp18
-rw-r--r--src/lib/netlist/plib/pdynlib.h15
-rw-r--r--src/lib/netlist/plib/pexception.cpp215
-rw-r--r--src/lib/netlist/plib/pexception.h214
-rw-r--r--src/lib/netlist/plib/pfmtlog.cpp121
-rw-r--r--src/lib/netlist/plib/pfmtlog.h50
-rw-r--r--src/lib/netlist/plib/pfunction.cpp32
-rw-r--r--src/lib/netlist/plib/pfunction.h4
-rw-r--r--src/lib/netlist/plib/plists.h122
-rw-r--r--src/lib/netlist/plib/pmain.cpp13
-rw-r--r--src/lib/netlist/plib/pmain.h20
-rw-r--r--src/lib/netlist/plib/pmatrix2d.h85
-rw-r--r--src/lib/netlist/plib/pmempool.h187
-rw-r--r--src/lib/netlist/plib/pomp.h28
-rw-r--r--src/lib/netlist/plib/poptions.cpp154
-rw-r--r--src/lib/netlist/plib/poptions.h161
-rw-r--r--src/lib/netlist/plib/pparser.cpp278
-rw-r--r--src/lib/netlist/plib/pparser.h107
-rw-r--r--src/lib/netlist/plib/ppmf.h28
-rw-r--r--src/lib/netlist/plib/pstate.cpp35
-rw-r--r--src/lib/netlist/plib/pstate.h67
-rw-r--r--src/lib/netlist/plib/pstream.cpp131
-rw-r--r--src/lib/netlist/plib/pstream.h408
-rw-r--r--src/lib/netlist/plib/pstring.cpp131
-rw-r--r--src/lib/netlist/plib/pstring.h457
-rw-r--r--src/lib/netlist/plib/ptime.h136
-rw-r--r--src/lib/netlist/plib/ptypes.h124
-rw-r--r--src/lib/netlist/plib/putil.cpp75
-rw-r--r--src/lib/netlist/plib/putil.h103
-rw-r--r--src/lib/netlist/plib/vector_ops.h151
38 files changed, 4004 insertions, 1497 deletions
diff --git a/src/lib/netlist/plib/gmres.h b/src/lib/netlist/plib/gmres.h
new file mode 100644
index 00000000000..2c357e97624
--- /dev/null
+++ b/src/lib/netlist/plib/gmres.h
@@ -0,0 +1,450 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * gmres.h
+ *
+ */
+
+#ifndef PLIB_GMRES_H_
+#define PLIB_GMRES_H_
+
+#include "mat_cr.h"
+#include "parray.h"
+#include "pconfig.h"
+#include "vector_ops.h"
+
+#include <algorithm>
+#include <cmath>
+
+
+namespace plib
+{
+
+ template <typename FT, int SIZE>
+ struct mat_precondition_ILU
+ {
+ using mat_type = plib::matrix_compressed_rows_t<FT, SIZE>;
+
+ mat_precondition_ILU(std::size_t size, int ilu_scale = 4
+ , std::size_t bw = plib::matrix_compressed_rows_t<FT, SIZE>::FILL_INFINITY)
+ : m_mat(static_cast<typename mat_type::index_type>(size))
+ , m_LU(static_cast<typename mat_type::index_type>(size))
+ , m_use_iLU_preconditioning(ilu_scale >= 0)
+ , m_ILU_scale(static_cast<std::size_t>(ilu_scale))
+ , m_band_width(bw)
+ {
+ }
+
+ template <typename M>
+ void build(M &fill)
+ {
+ m_mat.build_from_fill_mat(fill, 0);
+ if (m_use_iLU_preconditioning)
+ {
+ m_LU.gaussian_extend_fill_mat(fill);
+ m_LU.build_from_fill_mat(fill, m_ILU_scale, m_band_width); // ILU(2)
+ //m_LU.build_from_fill_mat(fill, 9999, 20); // Band matrix width 20
+ }
+ }
+
+
+ template<typename R, typename V>
+ void calc_rhs(R &rhs, const V &v)
+ {
+ m_mat.mult_vec(rhs, v);
+ }
+
+ void precondition()
+ {
+ if (m_use_iLU_preconditioning)
+ {
+ if (m_ILU_scale < 1)
+ m_LU.raw_copy_from(m_mat);
+ else
+ m_LU.reduction_copy_from(m_mat);
+ m_LU.incomplete_LU_factorization();
+ }
+ }
+
+ template<typename V>
+ void solve_LU_inplace(V &v)
+ {
+ if (m_use_iLU_preconditioning)
+ {
+ m_LU.solveLUx(v);
+ }
+ }
+
+ PALIGNAS_VECTOROPT()
+ mat_type m_mat;
+ PALIGNAS_VECTOROPT()
+ mat_type m_LU;
+ bool m_use_iLU_preconditioning;
+ std::size_t m_ILU_scale;
+ std::size_t m_band_width;
+ };
+
+ template <typename FT, int SIZE>
+ struct mat_precondition_diag
+ {
+ mat_precondition_diag(std::size_t size)
+ : m_mat(size)
+ , m_diag(size)
+ , m_use_iLU_preconditioning(true)
+ {
+ }
+
+ template <typename M>
+ void build(M &fill)
+ {
+ m_mat.build_from_fill_mat(fill, 0);
+ }
+
+ template<typename R, typename V>
+ void calc_rhs(R &rhs, const V &v)
+ {
+ m_mat.mult_vec(rhs, v);
+ }
+
+ void precondition()
+ {
+ if (m_use_iLU_preconditioning)
+ {
+ for (std::size_t i = 0; i< m_diag.size(); i++)
+ {
+ m_diag[i] = 1.0 / m_mat.A[m_mat.diag[i]];
+ }
+ }
+ }
+
+ template<typename V>
+ void solve_LU_inplace(V &v)
+ {
+ if (m_use_iLU_preconditioning)
+ {
+ for (std::size_t i = 0; i< m_diag.size(); i++)
+ v[i] = v[i] * m_diag[i];
+ }
+ }
+
+ plib::matrix_compressed_rows_t<FT, SIZE> m_mat;
+ plib::parray<FT, SIZE> m_diag;
+ bool m_use_iLU_preconditioning;
+ };
+
+ /* FIXME: hardcoding RESTART to 20 becomes an issue on very large
+ * systems.
+ */
+ template <typename FT, int SIZE, int RESTART = 20>
+ struct gmres_t
+ {
+ public:
+
+ using float_type = FT;
+ // FIXME: dirty hack to make this compile
+ static constexpr const std::size_t storage_N = plib::sizeabs<FT, SIZE>::ABS();
+
+ gmres_t(std::size_t size)
+ : residual(size)
+ , Ax(size)
+ , m_size(size)
+ , m_use_more_precise_stop_condition(false)
+ {
+ }
+
+ void givens_mult( const FT c, const FT s, FT & g0, FT & g1 )
+ {
+ const FT g0_last(g0);
+
+ g0 = c * g0 - s * g1;
+ g1 = s * g0_last + c * g1;
+ }
+
+ std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); }
+
+ template <typename OPS, typename VT, typename VRHS>
+ std::size_t solve(OPS &ops, VT &x, const VRHS & rhs, const std::size_t itr_max, float_type accuracy)
+ {
+ /*-------------------------------------------------------------------------
+ * The code below was inspired by code published by John Burkardt under
+ * the LPGL here:
+ *
+ * http://people.sc.fsu.edu/~jburkardt/cpp_src/mgmres/mgmres.html
+ *
+ * The code below was completely written from scratch based on the pseudo code
+ * found here:
+ *
+ * http://de.wikipedia.org/wiki/GMRES-Verfahren
+ *
+ * The Algorithm itself is described in
+ *
+ * Yousef Saad,
+ * Iterative Methods for Sparse Linear Systems,
+ * Second Edition,
+ * SIAM, 20003,
+ * ISBN: 0898715342,
+ * LC: QA188.S17.
+ *
+ *------------------------------------------------------------------------*/
+
+ std::size_t itr_used = 0;
+ double rho_delta = 0.0;
+
+ const std::size_t n = size();
+
+ ops.precondition();
+
+ if (m_use_more_precise_stop_condition)
+ {
+ /* derive residual for a given delta x
+ *
+ * LU y = A dx
+ *
+ * ==> rho / accuracy = sqrt(y * y)
+ *
+ * This approach will approximate the iterative stop condition
+ * based |xnew - xold| pretty precisely. But it is slow, or expressed
+ * differently: The invest doesn't pay off.
+ */
+
+ vec_set_scalar(n, residual, accuracy);
+ ops.calc_rhs(Ax, residual);
+
+ ops.solve_LU_inplace(Ax);
+
+ const float_type rho_to_accuracy = std::sqrt(vec_mult2<FT>(n, Ax)) / accuracy;
+
+ rho_delta = accuracy * rho_to_accuracy;
+ }
+ else
+ rho_delta = accuracy * std::sqrt(static_cast<FT>(n));
+
+ /*
+ * Using
+ *
+ * vec_set(n, x, rhs);
+ * ops.solve_LU_inplace(x);
+ *
+ * to get a starting point for x degrades convergence speed compared
+ * to using the last solution for x.
+ *
+ * LU x = b; solve for x;
+ *
+ */
+
+ while (itr_used < itr_max)
+ {
+ std::size_t last_k = RESTART;
+ float_type rho;
+
+ ops.calc_rhs(Ax, x);
+
+ vec_sub(n, residual, rhs, Ax);
+
+ ops.solve_LU_inplace(residual);
+
+ rho = std::sqrt(vec_mult2<FT>(n, residual));
+
+ if (rho < rho_delta)
+ return itr_used + 1;
+
+ /* FIXME: The "+" is necessary to avoid link issues
+ * on some systems / compiler versions. Issue reported by
+ * AJR, no details known yet.
+ */
+ vec_set_scalar(RESTART+1, m_g, +constants<FT>::zero());
+ m_g[0] = rho;
+
+ //for (std::size_t i = 0; i < mr + 1; i++)
+ // vec_set_scalar(mr, m_ht[i], NL_FCONST(0.0));
+
+ vec_mult_scalar(n, m_v[0], residual, constants<FT>::one() / rho);
+
+ for (std::size_t k = 0; k < RESTART; k++)
+ {
+ const std::size_t kp1 = k + 1;
+
+ ops.calc_rhs(m_v[kp1], m_v[k]);
+ ops.solve_LU_inplace(m_v[kp1]);
+
+ for (std::size_t j = 0; j <= k; j++)
+ {
+ m_ht[j][k] = vec_mult<FT>(n, m_v[kp1], m_v[j]);
+ vec_add_mult_scalar(n, m_v[kp1], m_v[j], -m_ht[j][k]);
+ }
+ m_ht[kp1][k] = std::sqrt(vec_mult2<FT>(n, m_v[kp1]));
+
+ if (m_ht[kp1][k] != 0.0)
+ vec_scale(n, m_v[kp1], constants<FT>::one() / m_ht[kp1][k]);
+
+ for (std::size_t j = 0; j < k; j++)
+ givens_mult(m_c[j], m_s[j], m_ht[j][k], m_ht[j+1][k]);
+
+ const float_type mu = 1.0 / std::hypot(m_ht[k][k], m_ht[kp1][k]);
+
+ m_c[k] = m_ht[k][k] * mu;
+ m_s[k] = -m_ht[kp1][k] * mu;
+ m_ht[k][k] = m_c[k] * m_ht[k][k] - m_s[k] * m_ht[kp1][k];
+ m_ht[kp1][k] = 0.0;
+
+ givens_mult(m_c[k], m_s[k], m_g[k], m_g[kp1]);
+
+ rho = std::abs(m_g[kp1]);
+
+ itr_used = itr_used + 1;
+
+ if (rho <= rho_delta)
+ {
+ last_k = k;
+ break;
+ }
+ }
+
+ if (last_k >= RESTART)
+ /* didn't converge within accuracy */
+ last_k = RESTART - 1;
+
+ /* Solve the system H * y = g */
+ /* x += m_v[j] * m_y[j] */
+ for (std::size_t i = last_k + 1; i-- > 0;)
+ {
+ double tmp = m_g[i];
+ for (std::size_t j = i + 1; j <= last_k; j++)
+ tmp -= m_ht[i][j] * m_y[j];
+ m_y[i] = tmp / m_ht[i][i];
+ }
+
+ for (std::size_t i = 0; i <= last_k; i++)
+ vec_add_mult_scalar(n, x, m_v[i], m_y[i]);
+
+ if (rho <= rho_delta)
+ break;
+
+ }
+ return itr_used;
+ }
+
+ private:
+
+ //typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype;
+
+ plib::parray<float_type, SIZE> residual;
+ plib::parray<float_type, SIZE> Ax;
+
+ plib::parray<float_type, RESTART + 1> m_c; /* mr + 1 */
+ plib::parray<float_type, RESTART + 1> m_g; /* mr + 1 */
+ plib::parray<plib::parray<float_type, RESTART>, RESTART + 1> m_ht; /* (mr + 1), mr */
+ plib::parray<float_type, RESTART + 1> m_s; /* mr + 1 */
+ plib::parray<float_type, RESTART + 1> m_y; /* mr + 1 */
+
+ //plib::parray<float_type, SIZE> m_v[RESTART + 1]; /* mr + 1, n */
+ plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */
+
+ std::size_t m_size;
+
+ bool m_use_more_precise_stop_condition;
+
+
+ };
+
+
+#if 0
+ /* Example of a Chebyshev iteration solver. This one doesn't work yet,
+ * it needs to be extended for non-symmetric matrix operation and
+ * depends on spectral radius estimates - which we don't have.
+ *
+ * Left here as another example.
+ */
+
+ template <typename FT, int SIZE>
+ struct ch_t
+ {
+ public:
+
+ typedef FT float_type;
+ // FIXME: dirty hack to make this compile
+ static constexpr const std::size_t storage_N = plib::sizeabs<FT, SIZE>::ABS();
+
+ // Maximum iterations before a restart ...
+ static constexpr const std::size_t restart_N = (storage_N > 0 ? 20 : 0);
+
+ ch_t(std::size_t size)
+ : residual(size)
+ , Ax(size)
+ , m_size(size)
+ {
+ }
+
+ std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); }
+
+ template <typename OPS, typename VT, typename VRHS>
+ std::size_t solve(OPS &ops, VT &x0, const VRHS & rhs, const std::size_t iter_max, float_type accuracy)
+ {
+ /*-------------------------------------------------------------------------
+ *
+ *
+ *------------------------------------------------------------------------*/
+
+ ops.precondition();
+
+ const FT lmax = 20.0;
+ const FT lmin = 0.0001;
+
+ const FT d = (lmax+lmin)/2.0;
+ const FT c = (lmax-lmin)/2.0;
+ FT alpha = 0;
+ FT beta = 0;
+ std::size_t itr_used = 0;
+
+ plib::parray<FT, SIZE> x(size());
+ plib::parray<FT, SIZE> p(size());
+
+ plib::vec_set(size(), x, x0);
+
+ ops.calc_rhs(Ax, x);
+ vec_sub(size(), rhs, Ax, residual);
+
+ FT rho_delta = accuracy * std::sqrt(static_cast<FT>(size()));
+
+ rho_delta = 1e-9;
+
+ for (int i = 0; i < iter_max; i++)
+ {
+ ops.solve_LU_inplace(residual);
+ if (i==0)
+ {
+ vec_set(size(), p, residual);
+ alpha = 2.0 / d;
+ }
+ else
+ {
+ beta = alpha * ( c / 2.0)*( c / 2.0);
+ alpha = 1.0 / (d - beta);
+ for (std::size_t k = 0; k < size(); k++)
+ p[k] = residual[k] + beta * p[k];
+ }
+ plib::vec_add_mult_scalar(size(), p, alpha, x);
+ ops.calc_rhs(Ax, x);
+ plib::vec_sub(size(), rhs, Ax, residual);
+ FT rho = std::sqrt(plib::vec_mult2<FT>(size(), residual));
+ if (rho < rho_delta)
+ break;
+ itr_used++;
+ }
+ return itr_used;
+ }
+ private:
+
+ //typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype;
+
+ plib::parray<float_type, SIZE> residual;
+ plib::parray<float_type, SIZE> Ax;
+
+ std::size_t m_size;
+
+ };
+#endif
+
+} // namespace plib
+
+#endif /* PLIB_GMRES_H_ */
diff --git a/src/lib/netlist/plib/mat_cr.h b/src/lib/netlist/plib/mat_cr.h
new file mode 100644
index 00000000000..4cc027f0d8f
--- /dev/null
+++ b/src/lib/netlist/plib/mat_cr.h
@@ -0,0 +1,530 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * mat_cr.h
+ *
+ * Compressed row format matrices
+ *
+ */
+
+#ifndef MAT_CR_H_
+#define MAT_CR_H_
+
+#include "palloc.h"
+#include "parray.h"
+#include "pconfig.h"
+#include "pomp.h"
+#include "pstate.h"
+#include "ptypes.h"
+#include "putil.h"
+
+#include <algorithm>
+#include <array>
+#include <cmath>
+#include <cstdlib>
+#include <type_traits>
+#include <vector>
+
+namespace plib
+{
+
+ // FIXME: causes a crash with GMRES handler
+ // template<typename T, int N, typename C = std::size_t>
+
+ template<typename T, int N, typename C = uint16_t>
+ struct matrix_compressed_rows_t
+ {
+ using index_type = C;
+ using value_type = T;
+
+ COPYASSIGNMOVE(matrix_compressed_rows_t, default)
+
+ enum constants_e
+ {
+ FILL_INFINITY = 9999999
+ };
+
+ parray<index_type, N> diag; // diagonal index pointer n
+ parray<index_type, (N == 0) ? 0 : (N < 0 ? N - 1 : N + 1)> row_idx; // row index pointer n + 1
+ parray<index_type, N < 0 ? -N * N : N *N> col_idx; // column index array nz_num, initially (n * n)
+ parray<value_type, N < 0 ? -N * N : N *N> A; // Matrix elements nz_num, initially (n * n)
+ //parray<C, N < 0 ? -N * (N-1) / 2 : N * (N+1) / 2 > nzbd; // Support for gaussian elimination
+ parray<std::vector<index_type>, N > nzbd; // Support for gaussian elimination
+ // contains elimination rows below the diagonal
+ // FIXME: convert to pvector
+ std::vector<std::vector<index_type>> m_ge_par;
+
+ index_type nz_num;
+
+ explicit matrix_compressed_rows_t(const index_type n)
+ : diag(n)
+ , row_idx(n+1)
+ , col_idx(n*n)
+ , A(n*n)
+ //, nzbd(n * (n+1) / 2)
+ , nzbd(n)
+ , nz_num(0)
+ , m_size(n)
+ {
+ for (index_type i=0; i<n+1; i++)
+ row_idx[i] = 0;
+ }
+
+ ~matrix_compressed_rows_t() = default;
+
+ constexpr index_type size() const { return static_cast<index_type>((N>0) ? N : m_size); }
+
+ void clear()
+ {
+ nz_num = 0;
+ for (index_type i=0; i < size() + 1; i++)
+ row_idx[i] = 0;
+ }
+
+ void set_scalar(const T scalar)
+ {
+ for (index_type i=0, e=nz_num; i<e; i++)
+ A[i] = scalar;
+ }
+
+ void set(C r, C c, T val)
+ {
+ C ri = row_idx[r];
+ while (ri < row_idx[r+1] && col_idx[ri] < c)
+ ri++;
+ // we have the position now;
+ if (ri < row_idx[r+1] && col_idx[ri] == c)
+ A[ri] = val;
+ else
+ {
+ for (C i = nz_num; i>ri; i--)
+ {
+ A[i] = A[i-1];
+ col_idx[i] = col_idx[i-1];
+ }
+ A[ri] = val;
+ col_idx[ri] = c;
+ for (C i = r + 1; i < size() + 1; i++)
+ row_idx[i]++;
+ nz_num++;
+ if (c==r)
+ diag[r] = ri;
+ }
+ }
+
+ template <typename M>
+ std::pair<std::size_t, std::size_t> gaussian_extend_fill_mat(M &fill)
+ {
+ std::size_t ops = 0;
+ std::size_t fill_max = 0;
+
+ for (std::size_t k = 0; k < fill.size(); k++)
+ {
+ ops++; // 1/A(k,k)
+ for (std::size_t row = k + 1; row < fill.size(); row++)
+ {
+ if (fill[row][k] < FILL_INFINITY)
+ {
+ ops++;
+ for (std::size_t col = k + 1; col < fill[row].size(); col++)
+ //if (fill[k][col] < FILL_INFINITY)
+ {
+ auto f = std::min(fill[row][col], 1 + fill[row][k] + fill[k][col]);
+ if (f < FILL_INFINITY)
+ {
+ if (f > fill_max)
+ fill_max = f;
+ ops += 2;
+ }
+ fill[row][col] = f;
+ }
+ }
+ }
+ }
+ build_parallel_gaussian_execution_scheme(fill);
+ return { fill_max, ops };
+ }
+
+ template <typename M>
+ void build_from_fill_mat(const M &f, std::size_t max_fill = FILL_INFINITY - 1,
+ std::size_t band_width = FILL_INFINITY)
+ {
+ C nz = 0;
+ if (nz_num != 0)
+ throw pexception("build_from_mat only allowed on empty CR matrix");
+ for (std::size_t k=0; k < size(); k++)
+ {
+ row_idx[k] = nz;
+
+ for (std::size_t j=0; j < size(); j++)
+ if (f[k][j] <= max_fill && std::abs(static_cast<int>(k)-static_cast<int>(j)) <= static_cast<int>(band_width))
+ {
+ col_idx[nz] = static_cast<C>(j);
+ if (j == k)
+ diag[k] = nz;
+ nz++;
+ }
+ }
+
+ row_idx[size()] = nz;
+ nz_num = nz;
+ /* build nzbd */
+
+ for (std::size_t k=0; k < size(); k++)
+ {
+ for (std::size_t j=k + 1; j < size(); j++)
+ if (f[j][k] < FILL_INFINITY)
+ nzbd[k].push_back(static_cast<C>(j));
+ nzbd[k].push_back(0); // end of sequence
+ }
+ }
+
+ template <typename V>
+ void gaussian_elimination(V & RHS)
+ {
+ const std::size_t iN = size();
+
+ for (std::size_t i = 0; i < iN - 1; i++)
+ {
+ std::size_t nzbdp = 0;
+ std::size_t pi = diag[i];
+ const value_type f = 1.0 / A[pi++];
+ const std::size_t piie = row_idx[i+1];
+ const auto &nz = nzbd[i];
+
+ while (auto j = nz[nzbdp++])
+ {
+ // proceed to column i
+
+ std::size_t pj = row_idx[j];
+
+ while (col_idx[pj] < i)
+ pj++;
+
+ const value_type f1 = - A[pj++] * f;
+
+ // subtract row i from j
+ // fill-in available assumed, i.e. matrix was prepared
+
+ for (std::size_t pii = pi; pii<piie; pii++)
+ {
+ while (col_idx[pj] < col_idx[pii])
+ pj++;
+ if (col_idx[pj] == col_idx[pii])
+ A[pj++] += A[pii] * f1;
+ }
+
+ RHS[j] += f1 * RHS[i];
+ }
+ }
+ }
+
+ template <typename V>
+ void gaussian_elimination_parallel(V & RHS)
+ {
+ // FIXME: move into solver creation ...
+ plib::omp::set_num_threads(4);
+ for (auto l = 0ul; l < m_ge_par.size(); l++)
+ plib::omp::for_static(0ul, m_ge_par[l].size(), [this, &RHS, &l] (unsigned ll)
+ {
+ auto &i = m_ge_par[l][ll];
+ {
+ std::size_t nzbdp = 0;
+ std::size_t pi = diag[i];
+ const value_type f = 1.0 / A[pi++];
+ const std::size_t piie = row_idx[i+1];
+
+ while (auto j = nzbd[i][nzbdp++])
+ {
+ // proceed to column i
+
+ std::size_t pj = row_idx[j];
+
+ while (col_idx[pj] < i)
+ pj++;
+
+ const value_type f1 = - A[pj++] * f;
+
+ // subtract row i from j
+ // fill-in available assumed, i.e. matrix was prepared
+ for (std::size_t pii = pi; pii<piie; pii++)
+ {
+ while (col_idx[pj] < col_idx[pii])
+ pj++;
+ if (col_idx[pj] == col_idx[pii])
+ A[pj++] += A[pii] * f1;
+ }
+ RHS[j] += f1 * RHS[i];
+ }
+ }
+ });
+ }
+
+ template <typename V1, typename V2>
+ void gaussian_back_substitution(V1 &V, const V2 &RHS)
+ {
+ const std::size_t iN = size();
+ /* row n-1 */
+ V[iN - 1] = RHS[iN - 1] / A[diag[iN - 1]];
+
+ for (std::size_t j = iN - 1; j-- > 0;)
+ {
+ value_type tmp = 0;
+ const auto jdiag = diag[j];
+ const std::size_t e = row_idx[j+1];
+ for (std::size_t pk = jdiag + 1; pk < e; pk++)
+ tmp += A[pk] * V[col_idx[pk]];
+ V[j] = (RHS[j] - tmp) / A[jdiag];
+ }
+ }
+
+ template <typename V1>
+ void gaussian_back_substitution(V1 &V)
+ {
+ const std::size_t iN = size();
+ /* row n-1 */
+ V[iN - 1] = V[iN - 1] / A[diag[iN - 1]];
+
+ for (std::size_t j = iN - 1; j-- > 0;)
+ {
+ value_type tmp = 0;
+ const auto jdiag = diag[j];
+ const std::size_t e = row_idx[j+1];
+ for (std::size_t pk = jdiag + 1; pk < e; pk++)
+ tmp += A[pk] * V[col_idx[pk]];
+ V[j] = (V[j] - tmp) / A[jdiag];
+ }
+ }
+
+
+ template <typename VTV, typename VTR>
+ void mult_vec(VTR & res, const VTV & x)
+ {
+ /*
+ * res = A * x
+ */
+
+ std::size_t row = 0;
+ std::size_t k = 0;
+ const std::size_t oe = nz_num;
+
+ while (k < oe)
+ {
+ T tmp = 0.0;
+ const std::size_t e = row_idx[row+1];
+ for (; k < e; k++)
+ tmp += A[k] * x[col_idx[k]];
+ res[row++] = tmp;
+ }
+ }
+
+ /* throws error if P(source)>P(destination) */
+ template <typename LUMAT>
+ void slim_copy_from(LUMAT & src)
+ {
+ for (std::size_t r=0; r<src.size(); r++)
+ {
+ C dp = row_idx[r];
+ for (C sp = src.row_idx[r]; sp < src.row_idx[r+1]; sp++)
+ {
+ /* advance dp to source column and fill 0s if necessary */
+ while (col_idx[dp] < src.col_idx[sp])
+ A[dp++] = 0;
+ if (row_idx[r+1] <= dp || col_idx[dp] != src.col_idx[sp])
+ throw plib::pexception("slim_copy_from error");
+ A[dp++] = src.A[sp];
+ }
+ /* fill remaining elements in row */
+ while (dp < row_idx[r+1])
+ A[dp++] = 0;
+ }
+ }
+
+ /* only copies common elements */
+ template <typename LUMAT>
+ void reduction_copy_from(LUMAT & src)
+ {
+ C sp = 0;
+ for (std::size_t r=0; r<src.size(); r++)
+ {
+ C dp = row_idx[r];
+ while(sp < src.row_idx[r+1])
+ {
+ /* advance dp to source column and fill 0s if necessary */
+ if (col_idx[dp] < src.col_idx[sp])
+ A[dp++] = 0;
+ else if (col_idx[dp] == src.col_idx[sp])
+ A[dp++] = src.A[sp++];
+ else
+ sp++;
+ }
+ /* fill remaining elements in row */
+ while (dp < row_idx[r+1])
+ A[dp++] = 0;
+ }
+ }
+
+ /* checks at all - may crash */
+ template <typename LUMAT>
+ void raw_copy_from(LUMAT & src)
+ {
+ for (std::size_t k = 0; k < nz_num; k++)
+ A[k] = src.A[k];
+ }
+
+ void incomplete_LU_factorization()
+ {
+ /*
+ * incomplete LU Factorization according to http://de.wikipedia.org/wiki/ILU-Zerlegung
+ *
+ * Result is stored in matrix LU
+ *
+ * For i = 1,...,N-1
+ * For k = 0, ... , i - 1
+ * If a[i,k] != 0
+ * a[i,k] = a[i,k] / a[k,k]
+ * For j = k + 1, ... , N - 1
+ * If a[i,j] != 0
+ * a[i,j] = a[i,j] - a[i,k] * a[k,j]
+ * j=j+1
+ * k=k+1
+ * i=i+1
+ *
+ */
+
+ for (std::size_t i = 1; i < size(); i++) // row i
+ {
+ const std::size_t p_i_end = row_idx[i + 1];
+ // loop over all columns k left of diag in row i
+ for (std::size_t i_k = row_idx[i]; i_k < diag[i]; i_k++)
+ {
+ const std::size_t k = col_idx[i_k];
+ const std::size_t p_k_end = row_idx[k + 1];
+ const T LUp_i_k = A[i_k] = A[i_k] / A[diag[k]];
+
+ std::size_t k_j = diag[k] + 1;
+ std::size_t i_j = i_k + 1;
+
+ while (i_j < p_i_end && k_j < p_k_end ) // pj = (i, j)
+ {
+ // we can assume that within a row ja increases continuously */
+ const std::size_t c_i_j = col_idx[i_j]; // row i, column j
+ const std::size_t c_k_j = col_idx[k_j]; // row i, column j
+ if (c_k_j < c_i_j)
+ k_j++;
+ else if (c_k_j == c_i_j)
+ A[i_j++] -= LUp_i_k * A[k_j++];
+ else
+ i_j++;
+ }
+ }
+ }
+ }
+
+ template <typename R>
+ void solveLUx (R &r)
+ {
+ /*
+ * Solve a linear equation Ax = r
+ * where
+ * A = L*U
+ *
+ * L unit lower triangular
+ * U upper triangular
+ *
+ * ==> LUx = r
+ *
+ * ==> Ux = L⁻¹ r = w
+ *
+ * ==> r = Lw
+ *
+ * This can be solved for w using backwards elimination in L.
+ *
+ * Now Ux = w
+ *
+ * This can be solved for x using backwards elimination in U.
+ *
+ */
+ for (std::size_t i = 1; i < size(); ++i )
+ {
+ T tmp = 0.0;
+ const std::size_t j1 = row_idx[i];
+ const std::size_t j2 = diag[i];
+
+ for (std::size_t j = j1; j < j2; ++j )
+ tmp += A[j] * r[col_idx[j]];
+ r[i] -= tmp;
+ }
+ // i now is equal to n;
+ for (std::size_t i = size(); i-- > 0; )
+ {
+ T tmp = 0.0;
+ const std::size_t di = diag[i];
+ const std::size_t j2 = row_idx[i+1];
+ for (std::size_t j = di + 1; j < j2; j++ )
+ tmp += A[j] * r[col_idx[j]];
+ r[i] = (r[i] - tmp) / A[di];
+ }
+ }
+ private:
+ template <typename M>
+ void build_parallel_gaussian_execution_scheme(const M &fill)
+ {
+ // calculate parallel scheme for gaussian elimination
+ std::vector<std::vector<index_type>> rt(size());
+ for (index_type k = 0; k < size(); k++)
+ {
+ for (index_type j = k+1; j < size(); j++)
+ {
+ if (fill[j][k] < FILL_INFINITY)
+ {
+ rt[k].push_back(j);
+ }
+ }
+ }
+
+ std::vector<index_type> levGE(size(), 0);
+ index_type cl = 0;
+
+ for (index_type k = 0; k < size(); k++ )
+ {
+ if (levGE[k] >= cl)
+ {
+ std::vector<index_type> t = rt[k];
+ for (index_type j = k+1; j < size(); j++ )
+ {
+ bool overlap = false;
+ // is there overlap
+ if (plib::container::contains(t, j))
+ overlap = true;
+ for (auto &x : rt[j])
+ if (plib::container::contains(t, x))
+ {
+ overlap = true;
+ break;
+ }
+ if (overlap)
+ levGE[j] = cl + 1;
+ else
+ {
+ t.push_back(j);
+ for (auto &x : rt[j])
+ t.push_back(x);
+ }
+ }
+ cl++;
+ }
+ }
+
+ m_ge_par.clear();
+ m_ge_par.resize(cl+1);
+ for (index_type k = 0; k < size(); k++)
+ m_ge_par[levGE[k]].push_back(k);
+ }
+
+ index_type m_size;
+ };
+
+} // namespace plib
+
+#endif /* MAT_CR_H_ */
diff --git a/src/lib/netlist/plib/palloc.cpp b/src/lib/netlist/plib/palloc.cpp
deleted file mode 100644
index e4d31985b23..00000000000
--- a/src/lib/netlist/plib/palloc.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * palloc.c
- *
- */
-
-#include "pconfig.h"
-#include "palloc.h"
-#include "pfmtlog.h"
-
-#include <algorithm>
-
-namespace plib {
-
-//============================================================
-// Memory pool
-//============================================================
-
-mempool::mempool(size_t min_alloc, size_t min_align)
-: m_min_alloc(min_alloc), m_min_align(min_align)
-{
-}
-mempool::~mempool()
-{
- for (auto & b : m_blocks)
- {
- if (b.m_num_alloc != 0)
- {
- fprintf(stderr, "Found block with %d dangling allocations\n", static_cast<int>(b.m_num_alloc));
- }
- ::operator delete(b.data);
- }
- m_blocks.clear();
-}
-
-size_t mempool::new_block()
-{
- block b;
- b.data = static_cast<char *>(::operator new(m_min_alloc));
- b.cur_ptr = b.data;
- b.m_free = m_min_alloc;
- b.m_num_alloc = 0;
- m_blocks.push_back(b);
- return m_blocks.size() - 1;
-}
-
-size_t mempool::mininfosize()
-{
- size_t sinfo = sizeof(mempool::info);
-#ifdef __APPLE__
- size_t ma = 16;
-#else
- size_t ma = 8;
-#endif
- return ((std::max(m_min_align, sinfo) + ma - 1) / ma) * ma;
-}
-
-void *mempool::alloc(size_t size)
-{
- size_t rs = (size + mininfosize() + m_min_align - 1) & ~(m_min_align - 1);
- for (size_t bn=0; bn < m_blocks.size(); bn++)
- {
- auto &b = m_blocks[bn];
- if (b.m_free > rs)
- {
- b.m_free -= rs;
- b.m_num_alloc++;
- auto i = reinterpret_cast<info *>(b.cur_ptr);
- i->m_block = bn;
- auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
- b.cur_ptr += rs;
- return ret;
- }
- }
- {
- size_t bn = new_block();
- auto &b = m_blocks[bn];
- b.m_num_alloc = 1;
- b.m_free = m_min_alloc - rs;
- auto i = reinterpret_cast<info *>(b.cur_ptr);
- i->m_block = bn;
- auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
- b.cur_ptr += rs;
- return ret;
- }
-}
-
-void mempool::free(void *ptr)
-{
- auto p = reinterpret_cast<char *>(ptr);
-
- auto i = reinterpret_cast<info *>(p - mininfosize());
- block *b = &m_blocks[i->m_block];
- if (b->m_num_alloc == 0)
- fprintf(stderr, "Argh .. double free\n");
- else
- {
- //b->m_free = m_min_alloc;
- //b->cur_ptr = b->data;
- }
- b->m_num_alloc--;
-}
-
-}
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index a35bc50ff17..15fede3a99b 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -8,172 +8,427 @@
#ifndef PALLOC_H_
#define PALLOC_H_
+#include "pconfig.h"
#include "pstring.h"
+#include "ptypes.h"
-#include <vector>
+#include <cstddef>
+#include <cstdlib>
#include <memory>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
+#include <malloc.h>
+#endif
namespace plib {
-//============================================================
-// Memory allocation
-//============================================================
-
-template<typename T, typename... Args>
-T *palloc(Args&&... args)
-{
- return new T(std::forward<Args>(args)...);
-}
-
-template<typename T>
-void pfree(T *ptr)
-{
- delete ptr;
-}
-
-template<typename T>
-T* palloc_array(const std::size_t num)
-{
- return new T[num]();
-}
-
-template<typename T>
-void pfree_array(T *ptr)
-{
- delete [] ptr;
-}
-
-template<typename T, typename... Args>
-std::unique_ptr<T> make_unique(Args&&... args)
-{
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-
-template<typename BC, typename DC, typename... Args>
-static std::unique_ptr<BC> make_unique_base(Args&&... args)
-{
- std::unique_ptr<BC> ret(new DC(std::forward<Args>(args)...));
- return ret;
-}
-
-template <typename SC>
-class owned_ptr
-{
-private:
- owned_ptr()
- : m_ptr(nullptr), m_is_owned(true) { }
-public:
- owned_ptr(SC *p, bool owned) noexcept
- : m_ptr(p), m_is_owned(owned)
- { }
-
- owned_ptr(const owned_ptr &r) = delete;
- owned_ptr & operator =(owned_ptr &r) = delete;
-
- template<typename DC>
- owned_ptr & operator =(owned_ptr<DC> &&r)
+ //============================================================
+ // Standard arena_deleter
+ //============================================================
+
+ template <typename P, typename T>
+ struct arena_deleter
+ {
+ //using arena_storage_type = P *;
+ using arena_storage_type = typename std::conditional<P::is_stateless, P, P *>::type;
+ template <typename X, typename Y = void>
+ typename std::enable_if<!X::is_stateless, X&>::type getref(X *x) { return *x;}
+ template <typename X, typename Y = void *>
+ typename std::enable_if<std::remove_pointer<X>::type::is_stateless, X&>::type
+ getref(X &x, Y y = nullptr)
+ {
+ unused_var(y);
+ return x;
+ }
+
+ constexpr arena_deleter(arena_storage_type a = arena_storage_type()) noexcept
+ : m_a(a) { }
+
+ template<typename PU, typename U, typename = typename
+ std::enable_if<std::is_convertible< U*, T*>::value>::type>
+ arena_deleter(const arena_deleter<PU, U> &rhs) noexcept : m_a(rhs.m_a) { }
+
+ void operator()(T *p) //const
+ {
+ /* call destructor */
+ p->~T();
+ getref(m_a).deallocate(p);
+ }
+ //private:
+ arena_storage_type m_a;
+ };
+
+ //============================================================
+ // owned_ptr: smart pointer with ownership information
+ //============================================================
+
+ template <typename SC, typename D>
+ class owned_ptr
+ {
+ public:
+
+ using pointer = SC *;
+ using element_type = SC;
+ using deleter_type = D;
+
+ owned_ptr()
+ : m_ptr(nullptr), m_deleter(), m_is_owned(true) { }
+
+ template <typename, typename>
+ friend class owned_ptr;
+
+ owned_ptr(pointer p, bool owned) noexcept
+ : m_ptr(p), m_deleter(), m_is_owned(owned)
+ { }
+
+ owned_ptr(pointer p, bool owned, D deleter) noexcept
+ : m_ptr(p), m_deleter(deleter), m_is_owned(owned)
+ { }
+
+
+ owned_ptr(const owned_ptr &r) = delete;
+ owned_ptr & operator =(owned_ptr &r) = delete;
+
+ template<typename DC, typename DC_D>
+ owned_ptr & operator =(owned_ptr<DC, DC_D> &&r)
+ {
+ if (m_is_owned && (m_ptr != nullptr))
+ //delete m_ptr;
+ m_deleter(m_ptr);
+ m_is_owned = r.m_is_owned;
+ m_ptr = r.m_ptr;
+ m_deleter = r.m_deleter;
+ r.m_is_owned = false;
+ r.m_ptr = nullptr;
+ return *this;
+ }
+
+ owned_ptr(owned_ptr &&r) noexcept
+ : m_ptr(r.m_ptr)
+ , m_deleter(r.m_deleter)
+ , m_is_owned(r.m_is_owned)
+ {
+ r.m_is_owned = false;
+ r.m_ptr = nullptr;
+ }
+
+ owned_ptr &operator=(owned_ptr &&r) noexcept
+ {
+ if (m_is_owned && (m_ptr != nullptr))
+ //delete m_ptr;
+ m_deleter(m_ptr);
+ m_is_owned = r.m_is_owned;
+ m_ptr = r.m_ptr;
+ m_deleter = std::move(r.m_deleter);
+ r.m_is_owned = false;
+ r.m_ptr = nullptr;
+ return *this;
+ }
+
+ template<typename DC, typename DC_D>
+ owned_ptr(owned_ptr<DC, DC_D> &&r) noexcept
+ : m_ptr(static_cast<pointer >(r.get()))
+ , m_deleter(r.m_deleter)
+ , m_is_owned(r.is_owned())
+ {
+ r.release();
+ }
+
+ ~owned_ptr() noexcept
+ {
+ if (m_is_owned && (m_ptr != nullptr))
+ {
+ //delete m_ptr;
+ m_deleter(m_ptr);
+ }
+ m_is_owned = false;
+ m_ptr = nullptr;
+ }
+
+ /**
+ * \brief Return @c true if the stored pointer is not null.
+ */
+ explicit operator bool() const noexcept { return m_ptr != nullptr; }
+
+ pointer release()
+ {
+ pointer tmp = m_ptr;
+ m_is_owned = false;
+ m_ptr = nullptr;
+ return tmp;
+ }
+
+ bool is_owned() const { return m_is_owned; }
+
+ pointer operator ->() const noexcept { return m_ptr; }
+ typename std::add_lvalue_reference<element_type>::type operator *() const noexcept { return *m_ptr; }
+ pointer get() const noexcept { return m_ptr; }
+
+ deleter_type& get_deleter() noexcept { return m_deleter; }
+ const deleter_type& get_deleter() const noexcept { return m_deleter; }
+
+ private:
+ pointer m_ptr;
+ D m_deleter;
+ bool m_is_owned;
+ };
+
+ //============================================================
+ // Arena allocator for use with containers
+ //============================================================
+
+ template <class ARENA, class T, std::size_t ALIGN = alignof(T)>
+ class arena_allocator
{
- if (m_is_owned && (m_ptr != nullptr))
- delete m_ptr;
- m_is_owned = r.m_is_owned;
- m_ptr = r.m_ptr;
- r.m_is_owned = false;
- r.m_ptr = nullptr;
- return *this;
+ public:
+ using value_type = T;
+ static constexpr const std::size_t align_size = ALIGN;
+ using arena_type = ARENA;
+
+ static_assert(align_size >= alignof(T) && (align_size % alignof(T)) == 0,
+ "ALIGN must be greater than alignof(T) and a multiple");
+
+ arena_allocator() noexcept
+ : m_a(arena_type::instance())
+ { }
+
+ ~arena_allocator() noexcept = default;
+
+ arena_allocator(const arena_allocator &rhs) noexcept = default;
+ arena_allocator& operator=(const arena_allocator&) noexcept = delete;
+
+ arena_allocator(arena_allocator&&) noexcept = default;
+ arena_allocator& operator=(arena_allocator&&) = delete;
+
+ arena_allocator(arena_type & a) noexcept : m_a(a)
+ {
+ }
+
+ template <class U>
+ arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs) noexcept
+ : m_a(rhs.m_a)
+ {
+ }
+
+ template <class U> struct rebind
+ {
+ using other = arena_allocator<ARENA, U, ALIGN>;
+ };
+
+ T* allocate(std::size_t n)
+ {
+ return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n));
+ }
+
+ void deallocate(T* p, std::size_t n) noexcept
+ {
+ unused_var(n);
+ m_a.deallocate(p);
+ }
+
+ template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
+ friend bool operator==(const arena_allocator<AR1, T1, A1>& lhs,
+ const arena_allocator<AR2, T2, A2>& rhs) noexcept;
+
+ template <class AU, class U, std::size_t A> friend class arena_allocator;
+ private:
+ arena_type &m_a;
+ };
+
+ template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
+ inline bool operator==(const arena_allocator<AR1, T1, A1>& lhs,
+ const arena_allocator<AR2, T2, A2>& rhs) noexcept
+ {
+ return A1 == A2 && rhs.m_a == lhs.m_a;
+ }
+ template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
+ inline bool operator!=(const arena_allocator<AR1, T1, A1>& lhs,
+ const arena_allocator<AR2, T2, A2>& rhs) noexcept
+ {
+ return !(lhs == rhs);
}
- owned_ptr(owned_ptr &&r) noexcept
+ //============================================================
+ // Memory allocation
+ //============================================================
+
+ struct aligned_arena
{
- m_is_owned = r.m_is_owned;
- m_ptr = r.m_ptr;
- r.m_is_owned = false;
- r.m_ptr = nullptr;
+ static constexpr const bool is_stateless = true;
+ template <class T, std::size_t ALIGN = alignof(T)>
+ using allocator_type = arena_allocator<aligned_arena, T, ALIGN>;
+
+ template <typename T>
+ using owned_pool_ptr = plib::owned_ptr<T, arena_deleter<aligned_arena, T>>;
+
+ static inline aligned_arena &instance()
+ {
+ static aligned_arena s_arena;
+ return s_arena;
+ }
+
+ static inline void *allocate( size_t alignment, size_t size )
+ {
+ #if (USE_ALIGNED_ALLOCATION)
+ #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
+ return _aligned_malloc(size, alignment);
+ #elif defined(__APPLE__)
+ void* p;
+ if (::posix_memalign(&p, alignment, size) != 0) {
+ p = nullptr;
+ }
+ return p;
+ #else
+ return aligned_alloc(alignment, size);
+ #endif
+ #else
+ unused_var(alignment);
+ return ::operator new(size);
+ #endif
+ }
+
+ static inline void deallocate( void *ptr )
+ {
+ #if (USE_ALIGNED_ALLOCATION)
+ // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
+ free(ptr);
+ #else
+ ::operator delete(ptr);
+ #endif
+ }
+
+ template<typename T, typename... Args>
+ owned_pool_ptr<T> make_poolptr(Args&&... args)
+ {
+ auto *mem = allocate(alignof(T), sizeof(T));
+ return owned_pool_ptr<T>(new (mem) T(std::forward<Args>(args)...), true, arena_deleter<aligned_arena, T>(*this));
+ }
+
+ };
+
+ template <typename T, std::size_t ALIGN>
+ /*inline */ C14CONSTEXPR T *assume_aligned_ptr(T *p) noexcept
+ {
+ static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
+ static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
+ //auto t = reinterpret_cast<std::uintptr_t>(p);
+ //if (t & (ALIGN-1))
+ // printf("alignment error!");
+#if (USE_ALIGNED_HINTS)
+ return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN));
+#else
+ return p;
+#endif
}
- template<typename DC>
- owned_ptr(owned_ptr<DC> &&r) noexcept
+ template <typename T, std::size_t ALIGN>
+ constexpr const T *assume_aligned_ptr(const T *p) noexcept
{
- m_ptr = static_cast<SC *>(r.get());
- m_is_owned = r.is_owned();
- r.release();
+ static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
+ static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
+#if (USE_ALIGNED_HINTS)
+ return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN));
+#else
+ return p;
+#endif
}
- ~owned_ptr()
+ // FIXME: remove
+ template<typename T, typename... Args>
+ inline T *pnew(Args&&... args)
{
- if (m_is_owned && (m_ptr != nullptr))
- delete m_ptr;
- m_is_owned = false;
- m_ptr = nullptr;
+ auto *p = aligned_arena::allocate(alignof(T), sizeof(T));
+ return new(p) T(std::forward<Args>(args)...);
}
- template<typename DC, typename... Args>
- static owned_ptr Create(Args&&... args)
+
+ template<typename T>
+ inline void pdelete(T *ptr)
{
- owned_ptr a;
- DC *x = new DC(std::forward<Args>(args)...);
- a.m_ptr = static_cast<SC *>(x);
- return std::move(a);
+ ptr->~T();
+ aligned_arena::deallocate(ptr);
}
- template<typename... Args>
- static owned_ptr Create(Args&&... args)
+
+ template <typename T>
+ using unique_ptr = std::unique_ptr<T, arena_deleter<aligned_arena, T>>;
+
+ template<typename T, typename... Args>
+ plib::unique_ptr<T> make_unique(Args&&... args)
{
- owned_ptr a;
- a.m_ptr = new SC(std::forward<Args>(args)...);
- return std::move(a);
+ return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...));
}
- SC * release()
+
+#if 0
+ template<typename T, typename... Args>
+ static owned_ptr<T> make_owned(Args&&... args)
{
- SC *tmp = m_ptr;
- m_is_owned = false;
- m_ptr = nullptr;
- return tmp;
+ return owned_ptr<T>(pnew<T>(std::forward<Args>(args)...), true);
}
+#endif
+
- bool is_owned() const { return m_is_owned; }
+ template <class T, std::size_t ALIGN = alignof(T)>
+ using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>;
- SC * operator ->() const { return m_ptr; }
- SC & operator *() const { return *m_ptr; }
- SC * get() const { return m_ptr; }
-private:
- SC *m_ptr;
- bool m_is_owned;
-};
+ //============================================================
+ // traits to determine alignment size and stride size
+ // from types supporting alignment
+ //============================================================
-class mempool
-{
-private:
- struct block
+ PDEFINE_HAS_MEMBER(has_align, align_size);
+
+ template <typename T, typename X = void>
+ struct align_traits
{
- block() : m_num_alloc(0), m_free(0), cur_ptr(nullptr), data(nullptr) { }
- std::size_t m_num_alloc;
- std::size_t m_free;
- char *cur_ptr;
- char *data;
+ static constexpr const std::size_t align_size = alignof(std::max_align_t);
+ static constexpr const std::size_t value_size = sizeof(typename T::value_type);
+ static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
};
- size_t new_block();
- size_t mininfosize();
-
- struct info
+ template <typename T>
+ struct align_traits<T, typename std::enable_if<has_align<T>::value, void>::type>
{
- info() : m_block(0) { }
- size_t m_block;
+ static constexpr const std::size_t align_size = T::align_size;
+ static constexpr const std::size_t value_size = sizeof(typename T::value_type);
+ static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
};
- size_t m_min_alloc;
- size_t m_min_align;
+ //============================================================
+ // Aligned vector
+ //============================================================
- std::vector<block> m_blocks;
+ // FIXME: needs a separate file
+ template <class T, std::size_t ALIGN = alignof(T)>
+ class aligned_vector : public std::vector<T, aligned_allocator<T, ALIGN>>
+ {
+ public:
+ using base = std::vector<T, aligned_allocator<T, ALIGN>>;
+
+ using reference = typename base::reference;
+ using const_reference = typename base::const_reference;
+ using pointer = typename base::pointer;
+ using const_pointer = typename base::const_pointer;
+ using size_type = typename base::size_type;
-public:
- mempool(size_t min_alloc, size_t min_align);
- ~mempool();
+ using base::base;
- void *alloc(size_t size);
- void free(void *ptr);
+ C14CONSTEXPR reference operator[](size_type i) noexcept
+ {
+ return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i];
+ }
+ constexpr const_reference operator[](size_type i) const noexcept
+ {
+ return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i];
+ }
-};
+ pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
+ const_pointer data() const noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
+
+ };
-}
+} // namespace plib
#endif /* PALLOC_H_ */
diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h
new file mode 100644
index 00000000000..1be37b908cd
--- /dev/null
+++ b/src/lib/netlist/plib/parray.h
@@ -0,0 +1,126 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * parray.h
+ *
+ */
+
+#ifndef PARRAY_H_
+#define PARRAY_H_
+
+#include "palloc.h"
+#include "pconfig.h"
+#include "pexception.h"
+
+#include <array>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace plib {
+
+ template <typename FT, int SIZE>
+ struct sizeabs
+ {
+ static constexpr std::size_t ABS() { return (SIZE < 0) ? static_cast<std::size_t>(0 - SIZE) : static_cast<std::size_t>(SIZE); }
+ using container = typename std::array<FT, ABS()> ;
+ };
+
+ template <typename FT>
+ struct sizeabs<FT, 0>
+ {
+ static constexpr const std::size_t ABS = 0;
+ using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
+ };
+
+ /**
+ * \brief Array with preallocated or dynamic allocation
+ *
+ * Passing SIZE > 0 has the same functionality as a std::array.
+ * SIZE = 0 is pure dynamic allocation, the actual array size is passed to the
+ * constructor.
+ * SIZE < 0 reserves std::abs(SIZE) elements statically in place allocated. The
+ * actual size is passed in by the constructor.
+ * This array is purely intended for HPC application where depending on the
+ * architecture a preference dynamic/static has to be made.
+ *
+ * This struct is not intended to be a full replacement to std::array.
+ * It is a subset to enable switching between dynamic and static allocation.
+ * I consider > 10% performance difference to be a use case.
+ */
+
+ template <typename FT, int SIZE>
+ struct parray
+ {
+ public:
+ static constexpr std::size_t SIZEABS() { return sizeabs<FT, SIZE>::ABS(); }
+
+ using base_type = typename sizeabs<FT, SIZE>::container;
+ using size_type = typename base_type::size_type;
+ using reference = typename base_type::reference;
+ using const_reference = typename base_type::const_reference;
+ using value_type = typename base_type::value_type;
+
+ template <int X = SIZE >
+ parray(size_type size, typename std::enable_if<X==0, int>::type = 0)
+ : m_a(size), m_size(size)
+ {
+ }
+
+#if 1
+ /* allow construction in fixed size arrays */
+ template <int X = SIZE >
+ parray(typename std::enable_if<(X > 0), int>::type = 0)
+ : m_size(X)
+ {
+ }
+#endif
+ template <int X = SIZE >
+ parray(size_type size, typename std::enable_if<X!=0, int>::type = 0)
+ : m_size(size)
+ {
+ if (SIZE < 0 && size > SIZEABS())
+ throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZEABS()));
+ else if (SIZE > 0 && size != SIZEABS())
+ throw plib::pexception("parray: size error");
+ }
+
+ inline size_type size() const noexcept { return SIZE <= 0 ? m_size : SIZEABS(); }
+
+ constexpr size_type max_size() const noexcept { return base_type::max_size(); }
+
+ bool empty() const noexcept { return size() == 0; }
+
+#if 0
+ reference operator[](size_type i) /*noexcept*/
+ {
+ if (i >= m_size) throw plib::pexception("limits error " + to_string(i) + ">=" + to_string(m_size));
+ return m_a[i];
+ }
+ const_reference operator[](size_type i) const /*noexcept*/
+ {
+ if (i >= m_size) throw plib::pexception("limits error " + to_string(i) + ">=" + to_string(m_size));
+ return m_a[i];
+ }
+#else
+ C14CONSTEXPR reference operator[](size_type i) noexcept
+ {
+ return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i];
+ }
+ constexpr const_reference operator[](size_type i) const noexcept
+ {
+ return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i];
+ }
+#endif
+ FT * data() noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); }
+ const FT * data() const noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); }
+
+ private:
+ PALIGNAS_VECTOROPT()
+ base_type m_a;
+ size_type m_size;
+ };
+} // namespace plib
+
+#endif /* PARRAY_H_ */
diff --git a/src/lib/netlist/plib/pchrono.cpp b/src/lib/netlist/plib/pchrono.cpp
index 971d19b3645..953d948e062 100644
--- a/src/lib/netlist/plib/pchrono.cpp
+++ b/src/lib/netlist/plib/pchrono.cpp
@@ -49,5 +49,5 @@ exact_ticks::type exact_ticks::per_second()
#endif
-}
-}
+} // namespace chrono
+} // namespace plib
diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h
index a229128e7b8..8ce0eca23b3 100644
--- a/src/lib/netlist/plib/pchrono.h
+++ b/src/lib/netlist/plib/pchrono.h
@@ -9,16 +9,17 @@
#define PCHRONO_H_
#include "pconfig.h"
+#include "ptypes.h"
-#include <cstdint>
#include <chrono>
+#include <cstdint>
namespace plib {
namespace chrono {
template <typename T>
struct sys_ticks
{
- typedef typename T::rep type;
+ using type = typename T::rep;
static inline type start() { return T::now().time_since_epoch().count(); }
static inline type stop() { return T::now().time_since_epoch().count(); }
static inline constexpr type per_second() { return T::period::den / T::period::num; }
@@ -145,7 +146,7 @@ namespace chrono {
struct counter
{
counter() : m_count(0) { }
- typedef uint_least64_t type;
+ using type = uint_least64_t;
type operator()() const { return m_count; }
void inc() { ++m_count; }
void reset() { m_count = 0; }
@@ -157,7 +158,7 @@ namespace chrono {
template<>
struct counter<false>
{
- typedef uint_least64_t type;
+ using type = uint_least64_t;
constexpr type operator()() const { return 0; }
void inc() const { }
void reset() const { }
@@ -168,15 +169,28 @@ namespace chrono {
template< typename T, bool enabled_ = true>
struct timer
{
- typedef typename T::type type;
- typedef uint_least64_t ctype;
+ using type = typename T::type;
+ using ctype = uint_least64_t;
+ constexpr static bool enabled = enabled_;
+
+ struct guard_t
+ {
+ guard_t() = delete;
+ guard_t(timer &m) noexcept : m_m(m) { m_m.m_time -= T::start(); }
+ ~guard_t() { m_m.m_time += T::stop(); ++m_m.m_count; }
+
+ COPYASSIGNMOVE(guard_t, default)
+
+ private:
+ timer &m_m;
+ };
+
+ friend struct guard_t;
timer() : m_time(0), m_count(0) { }
type operator()() const { return m_time; }
- void start() { m_time -= T::start(); }
- void stop() { m_time += T::stop(); ++m_count; }
void reset() { m_time = 0; m_count = 0; }
type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
type total() const { return m_time; }
@@ -185,7 +199,7 @@ namespace chrono {
double as_seconds() const { return static_cast<double>(total())
/ static_cast<double>(T::per_second()); }
- constexpr static bool enabled = enabled_;
+ guard_t guard() { return guard_t(*this); }
private:
type m_time;
ctype m_count;
@@ -194,19 +208,31 @@ namespace chrono {
template<typename T>
struct timer<T, false>
{
- typedef typename T::type type;
- typedef uint_least64_t ctype;
+ using type = typename T::type;
+ using ctype = uint_least64_t;
+
+ struct guard_t
+ {
+ guard_t() = default;
+ COPYASSIGNMOVE(guard_t, default)
+ /* using default constructor will trigger warning on
+ * unused local variable.
+ */
+ // NOLINTNEXTLINE(modernize-use-equals-default)
+ ~guard_t() { }
+ };
+
constexpr type operator()() const { return 0; }
- void start() const { }
- void stop() const { }
void reset() const { }
constexpr type average() const { return 0; }
constexpr type total() const { return 0; }
constexpr ctype count() const { return 0; }
constexpr double as_seconds() const { return 0.0; }
constexpr static bool enabled = false;
+ guard_t guard() { return guard_t(); }
};
+
} // namespace chrono
} // namespace plib
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index 0200c305ecd..d66b342f815 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -21,18 +21,46 @@
* if PHAS_RDTSCP == 1
*/
#ifndef PUSE_ACCURATE_STATS
-#define PUSE_ACCURATE_STATS (1)
+#define PUSE_ACCURATE_STATS (0)
#endif
/*
* Set this to one if you want to use 128 bit int for ptime.
- * This is for tests only.
+ * This is about 5% slower on a kaby lake processor.
*/
#ifndef PHAS_INT128
#define PHAS_INT128 (0)
#endif
+/*
+ * Set this to one if you want to use aligned storage optimizations.
+ */
+
+#ifndef USE_ALIGNED_OPTIMIZATIONS
+#define USE_ALIGNED_OPTIMIZATIONS (0)
+#endif
+
+#define USE_ALIGNED_ALLOCATION (USE_ALIGNED_OPTIMIZATIONS)
+#define USE_ALIGNED_HINTS (USE_ALIGNED_OPTIMIZATIONS)
+/*
+ * Standard alignment macros
+ */
+
+#define PALIGN_CACHELINE (64)
+#define PALIGN_VECTOROPT (64)
+
+#define PALIGNAS_CACHELINE() PALIGNAS(PALIGN_CACHELINE)
+#define PALIGNAS_VECTOROPT() PALIGNAS(PALIGN_VECTOROPT)
+
+/* Breaks mame build on windows due to -Wattribute
+ * FIXME: no error on cross-compile - need further checks */
+#if defined(_WIN32) && defined(__GNUC__)
+#define PALIGNAS(x)
+#else
+#define PALIGNAS(x) alignas(x)
+#endif
+
/*============================================================
* Check for CPP Version
*
@@ -47,6 +75,13 @@
*
*============================================================*/
+#ifndef NVCCBUILD
+#define NVCCBUILD (0)
+#endif
+
+#if NVCCBUILD
+#define C14CONSTEXPR
+#else
#if __cplusplus == 201103L
#define C14CONSTEXPR
#elif __cplusplus == 201402L
@@ -58,6 +93,7 @@
#else
#error "C++ version not supported"
#endif
+#endif
#ifndef PHAS_INT128
#define PHAS_INT128 (0)
@@ -68,17 +104,6 @@ typedef __uint128_t UINT128;
typedef __int128_t INT128;
#endif
-#if defined(__GNUC__)
-#ifdef RESTRICT
-#undef RESTRICT
-#endif
-#define RESTRICT __restrict__
-#define ATTR_UNUSED __attribute__((__unused__))
-#else
-#define RESTRICT
-#define ATTR_UNUSED
-#endif
-
//============================================================
// Standard defines
//============================================================
diff --git a/src/lib/netlist/plib/pdynlib.cpp b/src/lib/netlist/plib/pdynlib.cpp
index 13827eaf24c..0d32bead51d 100644
--- a/src/lib/netlist/plib/pdynlib.cpp
+++ b/src/lib/netlist/plib/pdynlib.cpp
@@ -25,7 +25,7 @@ CHAR *astring_from_utf8(const char *utf8string)
// convert UTF-16 to "ANSI code page" string
char_count = WideCharToMultiByte(CP_ACP, 0, wstring, -1, nullptr, 0, nullptr, nullptr);
- result = palloc_array<CHAR>(char_count);
+ result = new CHAR[char_count];
if (result != nullptr)
WideCharToMultiByte(CP_ACP, 0, wstring, -1, result, char_count, nullptr, nullptr);
@@ -39,7 +39,7 @@ WCHAR *wstring_from_utf8(const char *utf8string)
// convert MAME string (UTF-8) to UTF-16
char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, nullptr, 0);
- result = palloc_array<WCHAR>(char_count);
+ result = new WCHAR[char_count];
if (result != nullptr)
MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);
@@ -58,7 +58,7 @@ WCHAR *wstring_from_utf8(const char *utf8string)
#endif
namespace plib {
-dynlib::dynlib(const pstring libname)
+dynlib::dynlib(const pstring &libname)
: m_isLoaded(false), m_lib(nullptr)
{
#ifdef _WIN32
@@ -72,7 +72,7 @@ dynlib::dynlib(const pstring libname)
m_isLoaded = true;
//else
// fprintf(stderr, "win: library <%s> not found!\n", libname.c_str());
- pfree_array(buffer);
+ delete [] buffer;
#elif defined(EMSCRIPTEN)
//no-op
#else
@@ -88,9 +88,11 @@ dynlib::dynlib(const pstring libname)
#endif
}
-dynlib::dynlib(const pstring path, const pstring libname)
+dynlib::dynlib(const pstring &path, const pstring &libname)
: m_isLoaded(false), m_lib(nullptr)
{
+ // FIXME: implement path search
+ plib::unused_var(path);
// printf("win: loading <%s>\n", libname.c_str());
#ifdef _WIN32
TCHAR *buffer = tstring_from_utf8(libname.c_str());
@@ -104,7 +106,7 @@ dynlib::dynlib(const pstring path, const pstring libname)
{
//printf("win: library <%s> not found!\n", libname.c_str());
}
- pfree_array(buffer);
+ delete [] buffer;
#elif defined(EMSCRIPTEN)
//no-op
#else
@@ -139,7 +141,7 @@ bool dynlib::isLoaded() const
return m_isLoaded;
}
-void *dynlib::getsym_p(const pstring name)
+void *dynlib::getsym_p(const pstring &name)
{
#ifdef _WIN32
return (void *) GetProcAddress((HMODULE) m_lib, name.c_str());
@@ -148,4 +150,4 @@ void *dynlib::getsym_p(const pstring name)
#endif
}
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pdynlib.h b/src/lib/netlist/plib/pdynlib.h
index 7c9412593c9..1454c053298 100644
--- a/src/lib/netlist/plib/pdynlib.h
+++ b/src/lib/netlist/plib/pdynlib.h
@@ -8,28 +8,31 @@
#define PDYNLIB_H_
#include "pstring.h"
+#include "ptypes.h"
namespace plib {
// ----------------------------------------------------------------------------------------
// pdynlib: dynamic loading of libraries ...
// ----------------------------------------------------------------------------------------
-class dynlib
+class dynlib : public nocopyassignmove
{
public:
- explicit dynlib(const pstring libname);
- dynlib(const pstring path, const pstring libname);
+ explicit dynlib(const pstring &libname);
+ dynlib(const pstring &path, const pstring &libname);
+
~dynlib();
+ COPYASSIGNMOVE(dynlib, delete)
bool isLoaded() const;
template <typename T>
- T getsym(const pstring name)
+ T getsym(const pstring &name)
{
return reinterpret_cast<T>(getsym_p(name));
}
private:
- void *getsym_p(const pstring name);
+ void *getsym_p(const pstring &name);
bool m_isLoaded;
void *m_lib;
@@ -64,6 +67,6 @@ private:
calltype m_sym;
};
-}
+} // namespace plib
#endif /* PSTRING_H_ */
diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp
index a4ed8f367e0..8d6907d66f2 100644
--- a/src/lib/netlist/plib/pexception.cpp
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -9,6 +9,7 @@
#include "pfmtlog.h"
#include <cfenv>
+#include <iostream>
#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
#define HAS_FEENABLE_EXCEPT (1)
@@ -17,127 +18,113 @@
#endif
namespace plib {
-//============================================================
-// Exceptions
-//============================================================
-
-pexception::pexception(const pstring &text)
-: m_text(text)
-{
-}
-
-pexception::~pexception() noexcept
-{
-}
-
-file_e::file_e(const pstring &fmt, const pstring &filename)
- : pexception(pfmt(fmt)(filename))
-{
-}
-
-file_e::~file_e() noexcept
-{
-}
-
-file_open_e::file_open_e(const pstring &filename)
- : file_e("File open failed: {}", filename)
-{
-}
-
-file_open_e::~file_open_e() noexcept
-{
-
-}
-
-file_read_e::file_read_e(const pstring &filename)
- : file_e("File read failed: {}", filename)
-{
-}
-
-file_read_e::~file_read_e() noexcept
-{
-
-}
-
-file_write_e::file_write_e(const pstring &filename)
- : file_e("File write failed: {}", filename)
-{
-}
-
-file_write_e::~file_write_e() noexcept
-{
-}
-
-null_argument_e::null_argument_e(const pstring &argument)
- : pexception(pfmt("Null argument passed: {}")(argument))
-{
-}
-
-null_argument_e::~null_argument_e() noexcept
-{
-}
-
-out_of_mem_e::out_of_mem_e(const pstring &location)
- : pexception(pfmt("Out of memory: {}")(location))
-{
-}
-
-out_of_mem_e::~out_of_mem_e() noexcept
-{
-}
-
-fpexception_e::fpexception_e(const pstring &text)
- : pexception(pfmt("Out of memory: {}")(text))
-{
-}
-
-fpexception_e::~fpexception_e() noexcept
-{
-}
-
-bool fpsignalenabler::m_enable = false;
-
-fpsignalenabler::fpsignalenabler(unsigned fpexceptions)
-{
-#if HAS_FEENABLE_EXCEPT
- if (m_enable)
+
+ //============================================================
+ // terminate
+ //============================================================
+
+ void terminate(const pstring &msg) noexcept
{
- int b = 0;
- if (fpexceptions & plib::FP_INEXACT) b = b | FE_INEXACT;
- if (fpexceptions & plib::FP_DIVBYZERO) b = b | FE_DIVBYZERO;
- if (fpexceptions & plib::FP_UNDERFLOW) b = b | FE_UNDERFLOW;
- if (fpexceptions & plib::FP_OVERFLOW) b = b | FE_OVERFLOW;
- if (fpexceptions & plib::FP_INVALID) b = b | FE_INVALID;
- m_last_enabled = feenableexcept(b);
+ std::cerr << msg.c_str() << "\n";
+ std::terminate();
}
-#else
- m_last_enabled = 0;
-#endif
-}
-fpsignalenabler::~fpsignalenabler()
-{
-#if HAS_FEENABLE_EXCEPT
- if (m_enable)
+ //============================================================
+ // Exceptions
+ //============================================================
+
+ pexception::pexception(const pstring &text)
+ : m_text(text)
+ {
+ }
+
+
+ file_e::file_e(const pstring &fmt, const pstring &filename)
+ : pexception(pfmt(fmt)(filename))
+ {
+ }
+
+
+ file_open_e::file_open_e(const pstring &filename)
+ : file_e("File open failed: {}", filename)
+ {
+ }
+
+
+ file_read_e::file_read_e(const pstring &filename)
+ : file_e("File read failed: {}", filename)
{
- fedisableexcept(FE_ALL_EXCEPT); // Enable all floating point exceptions but FE_INEXACT
- feenableexcept(m_last_enabled); // Enable all floating point exceptions but FE_INEXACT
}
-#endif
-}
-bool fpsignalenabler::supported()
-{
- return true;
-}
-bool fpsignalenabler::global_enable(bool enable)
-{
- bool old = m_enable;
- m_enable = enable;
- return old;
-}
+ file_write_e::file_write_e(const pstring &filename)
+ : file_e("File write failed: {}", filename)
+ {
+ }
+
+
+ null_argument_e::null_argument_e(const pstring &argument)
+ : pexception(pfmt("Null argument passed: {}")(argument))
+ {
+ }
+
+
+ out_of_mem_e::out_of_mem_e(const pstring &location)
+ : pexception(pfmt("Out of memory: {}")(location))
+ {
+ }
+
+
+ fpexception_e::fpexception_e(const pstring &text)
+ : pexception(pfmt("Out of memory: {}")(text))
+ {
+ }
+
+
+ bool fpsignalenabler::m_enable = false;
+
+ fpsignalenabler::fpsignalenabler(unsigned fpexceptions)
+ {
+ #if HAS_FEENABLE_EXCEPT
+ if (m_enable)
+ {
+ int b = 0;
+ if (fpexceptions & plib::FP_INEXACT) b = b | FE_INEXACT;
+ if (fpexceptions & plib::FP_DIVBYZERO) b = b | FE_DIVBYZERO;
+ if (fpexceptions & plib::FP_UNDERFLOW) b = b | FE_UNDERFLOW;
+ if (fpexceptions & plib::FP_OVERFLOW) b = b | FE_OVERFLOW;
+ if (fpexceptions & plib::FP_INVALID) b = b | FE_INVALID;
+ m_last_enabled = feenableexcept(b);
+ }
+ #else
+ m_last_enabled = 0;
+ #endif
+ }
+
+
+ fpsignalenabler::~fpsignalenabler()
+ {
+ #if HAS_FEENABLE_EXCEPT
+ if (m_enable)
+ {
+ fedisableexcept(FE_ALL_EXCEPT); // Enable all floating point exceptions but FE_INEXACT
+ feenableexcept(m_last_enabled); // Enable all floating point exceptions but FE_INEXACT
+ }
+ #endif
+ }
+
+ bool fpsignalenabler::supported()
+ {
+ return true;
+ }
+
+ bool fpsignalenabler::global_enable(bool enable)
+ {
+ bool old = m_enable;
+ m_enable = enable;
+ return old;
+ }
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h
index 4827081b754..28a3ac1adf1 100644
--- a/src/lib/netlist/plib/pexception.h
+++ b/src/lib/netlist/plib/pexception.h
@@ -9,118 +9,116 @@
#define PEXCEPTION_H_
#include "pstring.h"
+#include "ptypes.h"
#include <exception>
namespace plib {
-//============================================================
-// exception base
-//============================================================
-
-class pexception : public std::exception
-{
-public:
- explicit pexception(const pstring &text);
- pexception(const pexception &e) : std::exception(e), m_text(e.m_text) { }
-
- virtual ~pexception() noexcept;
-
- const pstring &text() { return m_text; }
- const char* what() const noexcept override { return m_text.c_str(); }
-
-private:
- pstring m_text;
-};
-
-class file_e : public plib::pexception
-{
-public:
- file_e(const pstring &fmt, const pstring &filename);
- file_e(const file_e &e) : pexception(e) { }
- virtual ~file_e() noexcept;
-};
-
-class file_open_e : public file_e
-{
-public:
- explicit file_open_e(const pstring &filename);
- file_open_e(const file_open_e &e) : file_e(e) { }
- virtual ~file_open_e() noexcept;
-};
-
-class file_read_e : public file_e
-{
-public:
- explicit file_read_e(const pstring &filename);
- file_read_e(const file_read_e &e) : file_e(e) { }
- virtual ~file_read_e() noexcept;
-};
-
-class file_write_e : public file_e
-{
-public:
- explicit file_write_e(const pstring &filename);
- file_write_e(const file_write_e &e) : file_e(e) { }
- virtual ~file_write_e() noexcept;
-};
-
-class null_argument_e : public plib::pexception
-{
-public:
- explicit null_argument_e(const pstring &argument);
- null_argument_e(const null_argument_e &e) : pexception(e) { }
- virtual ~null_argument_e() noexcept;
-};
-
-class out_of_mem_e : public plib::pexception
-{
-public:
- explicit out_of_mem_e(const pstring &location);
- out_of_mem_e(const out_of_mem_e &e) : pexception(e) { }
- virtual ~out_of_mem_e() noexcept;
-};
-
-/* FIXME: currently only a stub for later use. More use could be added by
- * using “-fnon-call-exceptions" and sigaction to enable c++ exception supported.
- */
-
-class fpexception_e : public pexception
-{
-public:
- explicit fpexception_e(const pstring &text);
- fpexception_e(const fpexception_e &e) : pexception(e) { }
- virtual ~fpexception_e() noexcept;
-};
-
-static constexpr unsigned FP_INEXACT = 0x0001;
-static constexpr unsigned FP_DIVBYZERO = 0x0002;
-static constexpr unsigned FP_UNDERFLOW = 0x0004;
-static constexpr unsigned FP_OVERFLOW = 0x0008;
-static constexpr unsigned FP_INVALID = 0x00010;
-static constexpr unsigned FP_ALL = 0x0001f;
-
-/*
- * Catch SIGFPE on linux for debugging purposes.
- */
-
-class fpsignalenabler
-{
-public:
- explicit fpsignalenabler(unsigned fpexceptions);
- ~fpsignalenabler();
-
- /* is the functionality supported ? */
- static bool supported();
- /* returns last global enable state */
- static bool global_enable(bool enable);
-
-private:
- int m_last_enabled;
-
- static bool m_enable;
-};
-
-}
+ //============================================================
+ // terminate
+ //============================================================
+
+ /*! Terminate the program
+ *
+ * \note could be enhanced by setting a termination handler
+ */
+ [[noreturn]] void terminate(const pstring &msg) noexcept;
+
+ //============================================================
+ // exception base
+ //============================================================
+
+ class pexception : public std::exception
+ {
+ public:
+ explicit pexception(const pstring &text);
+
+ const pstring &text() { return m_text; }
+ const char* what() const noexcept override { return m_text.c_str(); }
+
+ private:
+ pstring m_text;
+ };
+
+ class file_e : public plib::pexception
+ {
+ public:
+ file_e(const pstring &fmt, const pstring &filename);
+ };
+
+ class file_open_e : public file_e
+ {
+ public:
+ explicit file_open_e(const pstring &filename);
+ };
+
+ class file_read_e : public file_e
+ {
+ public:
+ explicit file_read_e(const pstring &filename);
+ };
+
+ class file_write_e : public file_e
+ {
+ public:
+ explicit file_write_e(const pstring &filename);
+ };
+
+ class null_argument_e : public plib::pexception
+ {
+ public:
+ explicit null_argument_e(const pstring &argument);
+ };
+
+ class out_of_mem_e : public plib::pexception
+ {
+ public:
+ explicit out_of_mem_e(const pstring &location);
+ };
+
+ /* FIXME: currently only a stub for later use. More use could be added by
+ * using “-fnon-call-exceptions" and sigaction to enable c++ exception supported.
+ */
+
+ class fpexception_e : public pexception
+ {
+ public:
+ explicit fpexception_e(const pstring &text);
+ };
+
+ static constexpr unsigned FP_INEXACT = 0x0001;
+ static constexpr unsigned FP_DIVBYZERO = 0x0002;
+ static constexpr unsigned FP_UNDERFLOW = 0x0004;
+ static constexpr unsigned FP_OVERFLOW = 0x0008;
+ static constexpr unsigned FP_INVALID = 0x00010;
+ static constexpr unsigned FP_ALL = 0x0001f;
+
+ /*
+ * Catch SIGFPE on linux for debugging purposes.
+ */
+
+ class fpsignalenabler
+ {
+ public:
+ explicit fpsignalenabler(unsigned fpexceptions);
+
+ COPYASSIGNMOVE(fpsignalenabler, delete)
+
+ ~fpsignalenabler();
+
+ /* is the functionality supported ? */
+ static bool supported();
+ /* returns last global enable state */
+ static bool global_enable(bool enable);
+
+ private:
+ int m_last_enabled;
+
+ static bool m_enable;
+ };
+
+
+} // namespace plib
#endif /* PEXCEPTION_H_ */
diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp
index b8b5fcb3b91..af87251fbdf 100644
--- a/src/lib/netlist/plib/pfmtlog.cpp
+++ b/src/lib/netlist/plib/pfmtlog.cpp
@@ -8,83 +8,96 @@
#include "pfmtlog.h"
#include "palloc.h"
-#include <cstring>
-#include <cstdlib>
-#include <cstdarg>
#include <algorithm>
-#include <locale>
+#include <array>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <iostream>
+#include <locale>
namespace plib {
pfmt &pfmt::format_element(const char *l, const unsigned cfmt_spec, ...)
{
va_list ap;
- va_start(ap, cfmt_spec);
- pstring fmt("%");
- char buf[2048]; // FIXME
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
+ std::array<char, 2048> buf;
std::size_t sl;
+ bool found_abs = false;
m_arg++;
- pstring search("{");
- search += plib::to_string(m_arg);
- sl = search.length();
+ do {
+ pstring fmt("%");
+ va_start(ap, cfmt_spec);
+ found_abs = false;
+ buf[0] = 0;
+ pstring search("{");
+ search += plib::to_string(m_arg);
+ sl = search.size();
- auto p = m_str.find(search + ":");
- sl++; // ":"
- if (p == pstring::npos) // no further specifiers
- {
- p = m_str.find(search + "}");
- if (p == pstring::npos) // not found try default
- {
- sl = 2;
- p = m_str.find("{}");
- }
- if (p == pstring::npos)
+ auto p = m_str.find(search + ":");
+ sl++; // ":"
+ if (p == pstring::npos) // no further specifiers
{
- sl=1;
- p = m_str.find("{");
- if (p != pstring:: npos)
+ p = m_str.find(search + "}");
+ if (p == pstring::npos) // not found try default
{
- auto p1 = m_str.find("}", p);
- if (p1 != pstring::npos)
+ sl = 2;
+ p = m_str.find("{}");
+ }
+ else
+ // found absolute positional place holder
+ found_abs = true;
+ if (p == pstring::npos)
+ {
+ sl=2;
+ p = m_str.find("{:");
+ if (p != pstring:: npos)
{
- sl = p1 - p + 1;
- fmt += m_str.substr(p+1, p1 - p - 1);
+ auto p1 = m_str.find("}", p);
+ if (p1 != pstring::npos)
+ {
+ sl = p1 - p + 1;
+ fmt += m_str.substr(p+1, p1 - p - 1);
+ }
}
}
}
- }
- else
- {
- auto p1 = m_str.find("}", p);
- if (p1 != pstring::npos)
+ else
+ {
+ // found absolute positional place holder
+ auto p1 = m_str.find("}", p);
+ if (p1 != pstring::npos)
+ {
+ sl = p1 - p + 1;
+ fmt += ((m_arg>=10) ? m_str.substr(p+4, p1 - p - 4) : m_str.substr(p+3, p1 - p - 3));
+ found_abs = true;
+ }
+ }
+ pstring::value_type pend = fmt.at(fmt.size() - 1);
+ if (pstring("duxo").find(cfmt_spec) != pstring::npos)
{
- sl = p1 - p + 1;
- fmt += ((m_arg>=10) ? m_str.substr(p+4, p1 - p - 4) : m_str.substr(p+3, p1 - p - 3));
+ if (pstring("duxo").find(pend) == pstring::npos)
+ fmt += (pstring(l) + static_cast<pstring::value_type>(cfmt_spec));
+ else
+ fmt = plib::left(fmt, fmt.size() - 1) + pstring(l) + plib::right(fmt, 1);
+ }
+ else if (pstring("fge").find(cfmt_spec) != pstring::npos)
+ {
+ if (pstring("fge").find(pend) == pstring::npos)
+ fmt += cfmt_spec;
}
- }
- pstring::code_t pend = fmt.at(fmt.length() - 1);
- if (pstring("duxo").find(cfmt_spec) != pstring::npos)
- {
- if (pstring("duxo").find(pend) == pstring::npos)
- fmt += (pstring(l, pstring::UTF8) + cfmt_spec);
else
- fmt = fmt.left(fmt.length() - 1) + pstring(l, pstring::UTF8) + fmt.right(1);
- }
- else if (pstring("fge").find(cfmt_spec) != pstring::npos)
- {
- if (pstring("fge").find(pend) == pstring::npos)
fmt += cfmt_spec;
- }
- else
- fmt += cfmt_spec;
- vsprintf(buf, fmt.c_str(), ap);
- if (p != pstring::npos)
- m_str = m_str.substr(0, p) + pstring(buf, pstring::UTF8) + m_str.substr(p + sl);
- va_end(ap);
+ std::vsnprintf(buf.data(), buf.size(), fmt.c_str(), ap);
+ if (p != pstring::npos)
+ m_str = m_str.substr(0, p) + pstring(buf.data()) + m_str.substr(p + sl);
+ va_end(ap);
+ } while (found_abs);
return *this;
}
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h
index 9b7a85d8d8d..cb9b59c01ce 100644
--- a/src/lib/netlist/plib/pfmtlog.h
+++ b/src/lib/netlist/plib/pfmtlog.h
@@ -9,6 +9,7 @@
#include "pstring.h"
#include "ptypes.h"
+#include "putil.h"
#include <limits>
@@ -34,7 +35,6 @@ struct ptype_traits_base
template <>
struct ptype_traits_base<bool>
{
- static unsigned int cast(bool &x) { return static_cast<unsigned int>(x); }
static unsigned int cast(const bool &x) { return static_cast<unsigned int>(x); }
static const bool is_signed = std::numeric_limits<bool>::is_signed;
static const char *size_spec() { return ""; }
@@ -136,7 +136,6 @@ struct ptype_traits<double> : ptype_traits_base<double>
static char32_t fmt_spec() { return 'f'; }
};
-
template<>
struct ptype_traits<char *> : ptype_traits_base<char *>
{
@@ -144,6 +143,13 @@ struct ptype_traits<char *> : ptype_traits_base<char *>
static char32_t fmt_spec() { return 's'; }
};
+template<>
+struct ptype_traits<std::string> : ptype_traits_base<char *>
+{
+ static const char *cast(const std::string &x) { return x.c_str(); }
+ static char32_t fmt_spec() { return 's'; }
+};
+
class pfmt
{
public:
@@ -151,44 +157,57 @@ public:
: m_str(fmt), m_arg(0)
{
}
+ COPYASSIGNMOVE(pfmt, default)
- pfmt(const pfmt &rhs) : m_str(rhs.m_str), m_arg(rhs.m_arg) { }
-
- ~pfmt()
- {
- }
+ ~pfmt() noexcept = default;
operator pstring() const { return m_str; }
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & e(const double &x) {return format_element("", 'e', x); }
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & g(const double &x) {return format_element("", 'g', x); }
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & e(const float &x) {return format_element("", 'e', static_cast<double>(x)); }
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & g(const float &x) {return format_element("", 'g', static_cast<double>(x)); }
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt &operator ()(const void *x) {return format_element("", 'p', x); }
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt &operator ()(const pstring &x) {return format_element("", 's', x.c_str() ); }
template<typename T>
pfmt &operator ()(const T &x)
{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T>::size_spec(), ptype_traits<T>::fmt_spec(), ptype_traits<T>::cast(x));
}
template<typename T>
pfmt &operator ()(const T *x)
{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T *>::size_spec(), ptype_traits<T *>::fmt_spec(), ptype_traits<T *>::cast(x));
}
+ template<typename X, typename Y, typename... Args>
+ pfmt &operator()(X&& x, Y && y, Args&&... args)
+ {
+ return ((*this)(std::forward<X>(x)))(std::forward<Y>(y), std::forward<Args>(args)...);
+ }
+
template<typename T>
pfmt &x(const T &x)
{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T>::size_spec(), 'x', x);
}
template<typename T>
pfmt &o(const T &x)
{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T>::size_spec(), 'o', x);
}
@@ -203,11 +222,13 @@ private:
};
template <class T, bool build_enabled = true>
-class pfmt_writer_t : plib::nocopyassignmove
+class pfmt_writer_t
{
public:
explicit pfmt_writer_t() : m_enabled(true) { }
+ COPYASSIGNMOVE(pfmt_writer_t, delete)
+
/* runtime enable */
template<bool enabled, typename... Args>
void log(const pstring & fmt, Args&&... args) const
@@ -237,7 +258,7 @@ public:
bool is_enabled() const { return m_enabled; }
protected:
- ~pfmt_writer_t() { }
+ ~pfmt_writer_t() noexcept = default;
private:
pfmt &xlog(pfmt &fmt) const { return fmt; }
@@ -258,7 +279,10 @@ class plog_channel : public pfmt_writer_t<plog_channel<T, L, build_enabled>, bui
friend class pfmt_writer_t<plog_channel<T, L, build_enabled>, build_enabled>;
public:
explicit plog_channel(T &b) : pfmt_writer_t<plog_channel, build_enabled>(), m_base(b) { }
- ~plog_channel() { }
+
+ COPYASSIGNMOVE(plog_channel, delete)
+
+ ~plog_channel() noexcept = default;
protected:
void vdowrite(const pstring &ls) const
@@ -283,7 +307,9 @@ public:
error(proxy),
fatal(proxy)
{}
- virtual ~plog_base() {}
+
+ COPYASSIGNMOVE(plog_base, default)
+ virtual ~plog_base() noexcept = default;
plog_channel<T, plog_level::DEBUG, debug_enabled> debug;
plog_channel<T, plog_level::INFO> info;
@@ -293,7 +319,7 @@ public:
plog_channel<T, plog_level::FATAL> fatal;
};
-}
+} // namespace plib
template<typename T>
plib::pfmt& operator<<(plib::pfmt &p, T&& val) { return p(std::forward<T>(val)); }
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 79f09cb4a46..6a2179e0e6f 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -6,9 +6,9 @@
*/
#include "pfunction.h"
+#include "pexception.h"
#include "pfmtlog.h"
#include "putil.h"
-#include "pexception.h"
#include <cmath>
#include <stack>
@@ -17,7 +17,7 @@ namespace plib {
void pfunction::compile(const std::vector<pstring> &inputs, const pstring &expr)
{
- if (expr.startsWith("rpn:"))
+ if (plib::startsWith(expr, "rpn:"))
compile_postfix(inputs, expr.substr(4));
else
compile_infix(inputs, expr);
@@ -56,7 +56,7 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
{ rc.m_cmd = RAND; stk += 1; }
else
{
- for (unsigned i = 0; i < inputs.size(); i++)
+ for (std::size_t i = 0; i < inputs.size(); i++)
{
if (inputs[i] == cmd)
{
@@ -68,9 +68,9 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
}
if (rc.m_cmd != PUSH_INPUT)
{
- bool err = false;
rc.m_cmd = PUSH_CONST;
- rc.m_param = cmd.as_double(&err);
+ bool err;
+ rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, err);
if (err)
throw plib::pexception(plib::pfmt("nld_function: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
stk += 1;
@@ -84,11 +84,11 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
}
-static int get_prio(pstring v)
+static int get_prio(const pstring &v)
{
if (v == "(" || v == ")")
return 1;
- else if (v.left(1) >= "a" && v.left(1) <= "z")
+ else if (plib::left(v, 1) >= "a" && plib::left(v, 1) <= "z")
return 0;
else if (v == "*" || v == "/")
return 20;
@@ -113,12 +113,11 @@ void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring
{
// Shunting-yard infix parsing
std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
- std::vector<pstring> sexpr(plib::psplit(expr.replace_all(" ",""), sep));
+ std::vector<pstring> sexpr(plib::psplit(plib::replace_all(expr, pstring(" "), pstring("")), sep));
std::stack<pstring> opstk;
std::vector<pstring> postfix;
- //printf("dbg: %s\n", expr.c_str());
- for (unsigned i = 0; i < sexpr.size(); i++)
+ for (std::size_t i = 0; i < sexpr.size(); i++)
{
pstring &s = sexpr[i];
if (s=="(")
@@ -182,14 +181,15 @@ void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring
#define OP(OP, ADJ, EXPR) \
case OP: \
- ptr-=ADJ; \
- stack[ptr-1] = EXPR; \
+ ptr-= (ADJ); \
+ stack[ptr-1] = (EXPR); \
break;
double pfunction::evaluate(const std::vector<double> &values)
{
- double stack[20];
+ std::array<double, 20> stack = { 0 };
unsigned ptr = 0;
+ stack[0] = 0.0;
for (auto &rc : m_precompiled)
{
switch (rc.m_cmd)
@@ -199,8 +199,8 @@ double pfunction::evaluate(const std::vector<double> &values)
OP(SUB, 1, ST2 - ST1)
OP(DIV, 1, ST2 / ST1)
OP(POW, 1, std::pow(ST2, ST1))
- OP(SIN, 0, std::sin(ST2));
- OP(COS, 0, std::cos(ST2));
+ OP(SIN, 0, std::sin(ST2))
+ OP(COS, 0, std::cos(ST2))
case RAND:
stack[ptr++] = lfsr_random();
break;
@@ -215,4 +215,4 @@ double pfunction::evaluate(const std::vector<double> &values)
return stack[ptr-1];
}
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index 7d5984f9d15..fbb6c508333 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -8,8 +8,8 @@
#ifndef PFUNCTION_H_
#define PFUNCTION_H_
-#include "pstring.h"
#include "pstate.h"
+#include "pstring.h"
#include <vector>
@@ -112,6 +112,6 @@ namespace plib {
};
-}
+} // namespace plib
#endif /* PEXCEPTION_H_ */
diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h
index 5fefa658b83..c2fee9c2f8e 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -12,6 +12,8 @@
#include "pstring.h"
+#include <array>
+#include <type_traits>
#include <vector>
namespace plib {
@@ -29,14 +31,13 @@ class uninitialised_array_t
{
public:
- typedef C* iterator;
- typedef const C* const_iterator;
+ using iterator = C *;
+ using const_iterator = const C *;
- uninitialised_array_t()
- {
- }
+ uninitialised_array_t() noexcept = default;
- ~uninitialised_array_t()
+ COPYASSIGNMOVE(uninitialised_array_t, delete)
+ ~uninitialised_array_t() noexcept
{
for (std::size_t i=0; i<N; i++)
(*this)[i].~C();
@@ -51,7 +52,7 @@ public:
const C& operator[](const std::size_t &index) const noexcept
{
- return *reinterpret_cast<C *>(&m_buf[index]);
+ return *reinterpret_cast<const C *>(&m_buf[index]);
}
template<typename... Args>
@@ -75,7 +76,8 @@ protected:
private:
/* ensure proper alignment */
- typename std::aligned_storage<sizeof(C), alignof(C)>::type m_buf[N];
+ PALIGNAS_VECTOROPT()
+ std::array<typename std::aligned_storage<sizeof(C), alignof(C)>::type, N> m_buf;
};
// ----------------------------------------------------------------------------------------
@@ -83,6 +85,7 @@ private:
// the list allows insertions / deletions if used properly
// ----------------------------------------------------------------------------------------
+#if 0
template <class LC>
class linkedlist_t
{
@@ -152,9 +155,10 @@ public:
void remove(const LC *elem) noexcept
{
auto p = &m_head;
- for ( ; *p != elem; p = &((*p)->m_next))
+ while(*p != elem)
{
//nl_assert(*p != nullptr);
+ p = &((*p)->m_next);
}
(*p) = elem->m_next;
}
@@ -166,7 +170,105 @@ public:
private:
LC *m_head;
};
+#else
+template <class LC>
+class linkedlist_t
+{
+public:
+
+ struct element_t
+ {
+ public:
+
+ friend class linkedlist_t<LC>;
+
+ constexpr element_t() : m_next(nullptr), m_prev(nullptr) {}
+ ~element_t() noexcept = default;
+
+ COPYASSIGNMOVE(element_t, delete)
+
+ constexpr LC *next() const noexcept { return m_next; }
+ constexpr LC *prev() const noexcept { return m_prev; }
+ private:
+ LC * m_next;
+ LC * m_prev;
+ };
+
+ struct iter_t final : public std::iterator<std::forward_iterator_tag, LC>
+ {
+ private:
+ LC* p;
+ public:
+ explicit constexpr iter_t(LC* x) noexcept : p(x) { }
+ constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { }
+ iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
+ iter_t& operator=(const iter_t &rhs) noexcept { iter_t t(rhs); std::swap(*this, t); return *this; }
+ iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; }
+ iter_t& operator++() noexcept {p = p->next();return *this;}
+ // NOLINTNEXTLINE(cert-dcl21-cpp)
+ iter_t operator++(int) & noexcept {const iter_t tmp(*this); operator++(); return tmp;}
+
+ ~iter_t() = default;
+
+ constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;}
+ constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;}
+ /* constexpr */ LC& operator*() noexcept {return *p;}
+ /* constexpr */ LC* operator->() noexcept {return p;}
+
+ constexpr LC& operator*() const noexcept {return *p;}
+ constexpr LC* operator->() const noexcept {return p;}
+ };
+
+ constexpr linkedlist_t() : m_head(nullptr) {}
-}
+ constexpr iter_t begin() const noexcept { return iter_t(m_head); }
+ constexpr iter_t end() const noexcept { return iter_t(nullptr); }
+
+ void push_front(LC *elem) noexcept
+ {
+ if (m_head)
+ m_head->m_prev = elem;
+ elem->m_next = m_head;
+ elem->m_prev = nullptr;
+ m_head = elem;
+ }
+
+ void push_back(LC *elem) noexcept
+ {
+ LC ** p(&m_head);
+ LC * prev(nullptr);
+ while (*p != nullptr)
+ {
+ prev = *p;
+ p = &((*p)->m_next);
+ }
+ *p = elem;
+ elem->m_prev = prev;
+ elem->m_next = nullptr;
+ }
+
+ void remove(const LC *elem) noexcept
+ {
+ if (elem->m_prev)
+ elem->m_prev->m_next = elem->m_next;
+ else
+ m_head = elem->m_next;
+ if (elem->m_next)
+ elem->m_next->m_prev = elem->m_prev;
+ else
+ {
+ /* update tail */
+ }
+ }
+
+ LC *front() const noexcept { return m_head; }
+ void clear() noexcept { m_head = nullptr; }
+ constexpr bool empty() const noexcept { return (m_head == nullptr); }
+
+private:
+ LC *m_head;
+};
+#endif
+} // namespace plib
#endif /* PLISTS_H_ */
diff --git a/src/lib/netlist/plib/pmain.cpp b/src/lib/netlist/plib/pmain.cpp
index 93c4076bac2..b381d96dca7 100644
--- a/src/lib/netlist/plib/pmain.cpp
+++ b/src/lib/netlist/plib/pmain.cpp
@@ -23,7 +23,7 @@ namespace plib {
char *buf = new char[dst_char_count + 1];
WideCharToMultiByte(CP_UTF8, 0, w, wlen, buf, dst_char_count, nullptr, nullptr);
buf[dst_char_count] = 0;
- auto ret = pstring(buf, pstring::UTF8);
+ auto ret = pstring(buf);
delete [] buf;
return ret;
}
@@ -37,18 +37,13 @@ namespace plib {
: options()
, pout_strm()
, perr_strm()
- , pout(pout_strm)
- , perr(perr_strm)
+ , pout(&pout_strm)
+ , perr(&perr_strm)
{
}
- app::~app()
- {
-
- }
-
- int app::main_utfX(int argc, char *argv[])
+ int app::main_utfX(int argc, char **argv)
{
auto r = this->parse(argc, argv);
int ret = 0;
diff --git a/src/lib/netlist/plib/pmain.h b/src/lib/netlist/plib/pmain.h
index e2f84b90de6..4f4be779251 100644
--- a/src/lib/netlist/plib/pmain.h
+++ b/src/lib/netlist/plib/pmain.h
@@ -10,20 +10,21 @@
#ifndef PMAIN_H_
#define PMAIN_H_
+#include "palloc.h"
#include "poptions.h"
+#include "pstream.h"
#include "pstring.h"
#include "putil.h"
-#include "pstream.h"
-#include <memory>
#include <cwchar>
+#include <memory>
#ifdef _WIN32
#define PMAIN(appclass) \
extern "C" int wmain(int argc, wchar_t *argv[]) { return plib::app::mainrun<appclass, wchar_t>(argc, argv); }
#else
#define PMAIN(appclass) \
-int main(int argc, char *argv[]) { return plib::app::mainrun<appclass, char>(argc, argv); }
+int main(int argc, char **argv) { return plib::app::mainrun<appclass, char>(argc, argv); }
#endif
@@ -36,7 +37,10 @@ namespace plib {
{
public:
app();
- virtual ~app();
+
+ COPYASSIGNMOVE(app, delete)
+
+ virtual ~app() = default;
virtual pstring usage() = 0;
virtual int execute() = 0;
@@ -48,21 +52,21 @@ namespace plib {
plib::putf8_fmt_writer perr;
template <class C, typename T>
- static int mainrun(int argc, T *argv[])
+ static int mainrun(int argc, T **argv)
{
- auto a = std::unique_ptr<C>(new C);
+ auto a = plib::make_unique<C>();
return a->main_utfX(argc, argv);
}
private:
- int main_utfX(int argc, char *argv[]);
+ int main_utfX(int argc, char **argv);
#ifdef _WIN32
int main_utfX(int argc, wchar_t *argv[]);
#endif
};
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pmatrix2d.h b/src/lib/netlist/plib/pmatrix2d.h
new file mode 100644
index 00000000000..eab533688d7
--- /dev/null
+++ b/src/lib/netlist/plib/pmatrix2d.h
@@ -0,0 +1,85 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * pmatrix2d.h
+ *
+ * NxM regular matrix
+ *
+ */
+
+#ifndef PMATRIX2D_H_
+#define PMATRIX2D_H_
+
+#include "palloc.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstdlib>
+#include <type_traits>
+#include <vector>
+
+namespace plib
+{
+
+
+ template<typename T, typename A = aligned_allocator<T>>
+ class pmatrix2d
+ {
+ public:
+ using value_type = T;
+ using allocator_type = A;
+
+ static constexpr const std::size_t align_size = align_traits<A>::align_size;
+ static constexpr const std::size_t stride_size = align_traits<A>::stride_size;
+ pmatrix2d()
+ : m_N(0), m_M(0), m_stride(8), m_v()
+ {
+ }
+
+ pmatrix2d(std::size_t N, std::size_t M)
+ : m_N(N), m_M(M), m_v()
+ {
+ m_stride = ((M + stride_size-1) / stride_size) * stride_size;
+ m_v.resize(N * m_stride);
+ }
+
+ void resize(std::size_t N, std::size_t M)
+ {
+ m_N = N;
+ m_M = M;
+ m_stride = ((M + stride_size-1) / stride_size) * stride_size;
+ m_v.resize(N * m_stride);
+ }
+
+ C14CONSTEXPR T * operator[] (std::size_t row) noexcept
+ {
+ return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]);
+ }
+
+ constexpr const T * operator[] (std::size_t row) const noexcept
+ {
+ return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]);
+ }
+
+ T & operator()(std::size_t r, std::size_t c) noexcept
+ {
+ return (*this)[r][c];
+ }
+
+ const T & operator()(std::size_t r, std::size_t c) const noexcept
+ {
+ return (*this)[r][c];
+ }
+
+ private:
+
+ std::size_t m_N;
+ std::size_t m_M;
+ std::size_t m_stride;
+
+ std::vector<T, A> m_v;
+ };
+
+} // namespace plib
+
+#endif /* MAT_CR_H_ */
diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h
new file mode 100644
index 00000000000..f55807c86dc
--- /dev/null
+++ b/src/lib/netlist/plib/pmempool.h
@@ -0,0 +1,187 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * pmempool.h
+ *
+ */
+
+#ifndef PMEMPOOL_H_
+#define PMEMPOOL_H_
+
+#include "palloc.h"
+#include "pstream.h"
+#include "pstring.h"
+#include "ptypes.h"
+#include "putil.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <memory>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+namespace plib {
+
+ //============================================================
+ // Memory pool
+ //============================================================
+
+ class mempool
+ {
+ private:
+ struct block
+ {
+ block(mempool *mp, std::size_t min_bytes)
+ : m_num_alloc(0)
+ , m_cur(0)
+ , m_data(nullptr)
+ , m_mempool(mp)
+ {
+ min_bytes = std::max(mp->m_min_alloc, min_bytes);
+ m_free = min_bytes;
+ std::size_t alloc_bytes = (min_bytes + mp->m_min_align - 1) & ~(mp->m_min_align - 1);
+ m_data_allocated = static_cast<char *>(::operator new(alloc_bytes));
+ void *r = m_data_allocated;
+ std::align(mp->m_min_align, min_bytes, r, alloc_bytes);
+ m_data = reinterpret_cast<char *>(r);
+ }
+ std::size_t m_num_alloc;
+ std::size_t m_free;
+ std::size_t m_cur;
+ char *m_data;
+ char *m_data_allocated;
+ mempool *m_mempool;
+ };
+
+ struct info
+ {
+ info(block *b, std::size_t p) : m_block(b), m_pos(p) { }
+ ~info() = default;
+ COPYASSIGNMOVE(info, default)
+
+ block * m_block;
+ std::size_t m_pos;
+ };
+
+
+ block * new_block(std::size_t min_bytes)
+ {
+ auto *b = plib::pnew<block>(this, min_bytes);
+ m_blocks.push_back(b);
+ return b;
+ }
+
+
+ static std::unordered_map<void *, info> &sinfo()
+ {
+ static std::unordered_map<void *, info> spinfo;
+ return spinfo;
+ }
+
+ size_t m_min_alloc;
+ size_t m_min_align;
+
+ std::vector<block *> m_blocks;
+
+ public:
+ static constexpr const bool is_stateless = false;
+ template <class T, std::size_t ALIGN = alignof(T)>
+ using allocator_type = arena_allocator<mempool, T, ALIGN>;
+
+ mempool(size_t min_alloc = (1<<21), size_t min_align = 16)
+ : m_min_alloc(min_alloc), m_min_align(min_align)
+ {
+ }
+
+ COPYASSIGNMOVE(mempool, delete)
+
+ ~mempool()
+ {
+
+ for (auto & b : m_blocks)
+ {
+ if (b->m_num_alloc != 0)
+ {
+ plib::perrlogger("Found {} info blocks\n", sinfo().size());
+ plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc);
+ }
+ ::operator delete(b->m_data);
+ }
+ }
+
+ void *allocate(size_t align, size_t size)
+ {
+ if (align < m_min_align)
+ align = m_min_align;
+
+ size_t rs = size + align;
+ for (auto &b : m_blocks)
+ {
+ if (b->m_free > rs)
+ {
+ b->m_free -= rs;
+ b->m_num_alloc++;
+ auto *ret = reinterpret_cast<void *>(b->m_data + b->m_cur);
+ auto capacity(rs);
+ ret = std::align(align, size, ret, capacity);
+ // FIXME: if (ret == nullptr)
+ // printf("Oh no\n");
+ sinfo().insert({ ret, info(b, b->m_cur)});
+ rs -= (capacity - size);
+ b->m_cur += rs;
+
+ return ret;
+ }
+ }
+ {
+ block *b = new_block(rs);
+ b->m_num_alloc = 1;
+ b->m_free = m_min_alloc - rs;
+ auto *ret = reinterpret_cast<void *>(b->m_data + b->m_cur);
+ auto capacity(rs);
+ ret = std::align(align, size, ret, capacity);
+ // FIXME: if (ret == nullptr)
+ // printf("Oh no\n");
+ sinfo().insert({ ret, info(b, b->m_cur)});
+ rs -= (capacity - size);
+ b->m_cur += rs;
+ return ret;
+ }
+ }
+
+ static void deallocate(void *ptr)
+ {
+
+ auto it = sinfo().find(ptr);
+ if (it == sinfo().end())
+ plib::terminate("mempool::free - pointer not found\n");
+ info i = it->second;
+ block *b = i.m_block;
+ if (b->m_num_alloc == 0)
+ plib::terminate("mempool::free - double free was called\n");
+ else
+ {
+ //b->m_free = m_min_alloc;
+ //b->cur_ptr = b->data;
+ }
+ b->m_num_alloc--;
+ //printf("Freeing in block %p %lu\n", b, b->m_num_alloc);
+ sinfo().erase(it);
+ }
+
+ template <typename T>
+ using owned_pool_ptr = plib::owned_ptr<T, arena_deleter<mempool, T>>;
+
+ template<typename T, typename... Args>
+ owned_pool_ptr<T> make_poolptr(Args&&... args)
+ {
+ auto *mem = this->allocate(alignof(T), sizeof(T));
+ return owned_pool_ptr<T>(new (mem) T(std::forward<Args>(args)...), true, arena_deleter<mempool, T>(this));
+ }
+
+ };
+
+} // namespace plib
+
+#endif /* PMEMPOOL_H_ */
diff --git a/src/lib/netlist/plib/pomp.h b/src/lib/netlist/plib/pomp.h
index 6559207f09d..f8a516df485 100644
--- a/src/lib/netlist/plib/pomp.h
+++ b/src/lib/netlist/plib/pomp.h
@@ -11,6 +11,8 @@
#include "pconfig.h"
+#include <cstddef>
+
#if HAS_OPENMP
#include "omp.h"
#endif
@@ -18,29 +20,39 @@
namespace plib {
namespace omp {
-template <class T>
-void for_static(const int start, const int end, const T &what)
+template <typename I, class T>
+void for_static(const I start, const I end, const T &what)
{
#if HAS_OPENMP && USE_OPENMP
#pragma omp parallel
#endif
{
#if HAS_OPENMP && USE_OPENMP
- #pragma omp for schedule(static)
+ #pragma omp for //schedule(static)
#endif
- for (int i = start; i < end; i++)
+ for (I i = start; i < end; i++)
what(i);
}
}
-inline void set_num_threads(const int threads)
+template <typename I, class T>
+void for_static_np(const I start, const I end, const T &what)
+{
+ for (I i = start; i < end; i++)
+ what(i);
+}
+
+
+inline void set_num_threads(const std::size_t threads)
{
#if HAS_OPENMP && USE_OPENMP
omp_set_num_threads(threads);
+#else
+ plib::unused_var(threads);
#endif
}
-inline int get_max_threads()
+inline std::size_t get_max_threads()
{
#if HAS_OPENMP && USE_OPENMP
return omp_get_max_threads();
@@ -54,7 +66,7 @@ inline int get_max_threads()
// pdynlib: dynamic loading of libraries ...
// ----------------------------------------------------------------------------------------
-}
-}
+} // namespace omp
+} // namespace plib
#endif /* PSTRING_H_ */
diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp
index 910660acb3d..4a3d32c4723 100644
--- a/src/lib/netlist/plib/poptions.cpp
+++ b/src/lib/netlist/plib/poptions.cpp
@@ -6,77 +6,39 @@
*/
#include "poptions.h"
+#include "pexception.h"
+#include "ptypes.h"
namespace plib {
/***************************************************************************
Options
***************************************************************************/
- option_base::option_base(options &parent, pstring help)
+ option_base::option_base(options &parent, const pstring &help)
: m_help(help)
{
parent.register_option(this);
}
- option_base::~option_base()
- {
- }
-
- option_group::~option_group()
- {
- }
-
- option_example::~option_example()
- {
- }
-
- option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument)
+ option::option(options &parent, const pstring &ashort, const pstring &along, const pstring &help, bool has_argument)
: option_base(parent, help), m_short(ashort), m_long(along),
m_has_argument(has_argument), m_specified(false)
{
}
- option::~option()
- {
- }
-
int option_str::parse(const pstring &argument)
{
m_val = argument;
return 0;
}
- int option_str_limit::parse(const pstring &argument)
- {
- if (plib::container::contains(m_limit, argument))
- {
- m_val = argument;
- return 0;
- }
- else
- return 1;
- }
-
int option_bool::parse(const pstring &argument)
{
+ unused_var(argument);
m_val = true;
return 0;
}
- int option_double::parse(const pstring &argument)
- {
- bool err = false;
- m_val = argument.as_double(&err);
- return (err ? 1 : 0);
- }
-
- int option_long::parse(const pstring &argument)
- {
- bool err = false;
- m_val = argument.as_long(&err);
- return (err ? 1 : 0);
- }
-
int option_vec::parse(const pstring &argument)
{
bool err = false;
@@ -85,53 +47,88 @@ namespace plib {
}
options::options()
+ : m_other_args(nullptr)
{
}
- options::options(option *o[])
+ options::options(option **o)
+ : m_other_args(nullptr)
{
int i=0;
while (o[i] != nullptr)
{
- m_opts.push_back(o[i]);
+ register_option(o[i]);
i++;
}
}
- options::~options()
+ void options::register_option(option_base *opt)
{
- m_opts.clear();
+ m_opts.push_back(opt);
}
- void options::register_option(option_base *opt)
+ void options::check_consistency()
{
- m_opts.push_back(opt);
+ for (auto &opt : m_opts)
+ {
+ auto *o = dynamic_cast<option *>(opt);
+ if (o != nullptr)
+ {
+ if (o->short_opt() == "" && o->long_opt() == "")
+ {
+ auto *ov = dynamic_cast<option_args *>(o);
+ if (ov != nullptr)
+ {
+ if (m_other_args != nullptr)
+ {
+ throw pexception("other args can only be specified once!");
+ }
+ else
+ {
+ m_other_args = ov;
+ }
+ }
+ else
+ throw pexception("found option with neither short or long tag!" );
+ }
+ }
+ }
}
- int options::parse(int argc, char *argv[])
+ int options::parse(int argc, char **argv)
{
- m_app = pstring(argv[0], pstring::UTF8);
+ check_consistency();
+ m_app = pstring(argv[0]);
+ bool seen_other_args = false;
for (int i=1; i<argc; )
{
- pstring arg(argv[i], pstring::UTF8);
+ pstring arg(argv[i]);
option *opt = nullptr;
pstring opt_arg;
bool has_equal_arg = false;
- if (arg.startsWith("--"))
+ if (!seen_other_args && plib::startsWith(arg, "--"))
{
auto v = psplit(arg.substr(2),"=");
- opt = getopt_long(v[0]);
- has_equal_arg = (v.size() > 1);
- if (has_equal_arg)
+ if (v.size() && v[0] != pstring(""))
{
- for (unsigned j = 1; j < v.size() - 1; j++)
- opt_arg = opt_arg + v[j] + "=";
- opt_arg += v[v.size()-1];
+ opt = getopt_long(v[0]);
+ has_equal_arg = (v.size() > 1);
+ if (has_equal_arg)
+ {
+ for (std::size_t j = 1; j < v.size() - 1; j++)
+ opt_arg = opt_arg + v[j] + "=";
+ opt_arg += v[v.size()-1];
+ }
+ }
+ else
+ {
+ opt = m_other_args;
+ seen_other_args = true;
}
}
- else if (arg.startsWith("-"))
+ else if (!seen_other_args && plib::startsWith(arg, "-"))
{
std::size_t p = 1;
opt = getopt_short(arg.substr(p, 1));
@@ -144,7 +141,11 @@ namespace plib {
}
else
{
- return i;
+ seen_other_args = true;
+ if (m_other_args == nullptr)
+ return i;
+ opt = m_other_args;
+ i--; // we haven't had an option specifier;
}
if (opt == nullptr)
return i;
@@ -158,7 +159,7 @@ namespace plib {
else
{
i++; // FIXME: are there more arguments?
- if (opt->do_parse(pstring(argv[i], pstring::UTF8)) != 0)
+ if (opt->do_parse(pstring(argv[i])) != 0)
return i - 1;
}
}
@@ -173,7 +174,7 @@ namespace plib {
return argc;
}
- pstring options::split_paragraphs(pstring text, unsigned width, unsigned indent,
+ pstring options::split_paragraphs(const pstring &text, unsigned width, unsigned indent,
unsigned firstline_indent)
{
auto paragraphs = psplit(text,"\n");
@@ -181,13 +182,13 @@ namespace plib {
for (auto &p : paragraphs)
{
- pstring line = pstring("").rpad(" ", firstline_indent);
+ pstring line = plib::rpad(pstring(""), pstring(" "), firstline_indent);
for (auto &s : psplit(p, " "))
{
if (line.length() + s.length() > width)
{
ret += line + "\n";
- line = pstring("").rpad(" ", indent);
+ line = plib::rpad(pstring(""), pstring(" "), indent);
}
line += s + " ";
}
@@ -196,8 +197,8 @@ namespace plib {
return ret;
}
- pstring options::help(pstring description, pstring usage,
- unsigned width, unsigned indent)
+ pstring options::help(const pstring &description, const pstring &usage,
+ unsigned width, unsigned indent) const
{
pstring ret;
@@ -206,6 +207,10 @@ namespace plib {
for (auto & optbase : m_opts )
{
+ // Skip anonymous inputs which are collected in option_args
+ if (dynamic_cast<option_args *>(optbase) != nullptr)
+ continue;
+
if (auto opt = dynamic_cast<option *>(optbase))
{
pstring line = "";
@@ -221,20 +226,20 @@ namespace plib {
if (opt->has_argument())
{
line += "=";
- option_str_limit *ol = dynamic_cast<option_str_limit *>(opt);
+ auto *ol = dynamic_cast<option_str_limit_base *>(opt);
if (ol)
{
for (auto &v : ol->limit())
{
line += v + "|";
}
- line = line.left(line.length() - 1);
+ line = plib::left(line, line.length() - 1);
}
else
line += "Value";
}
}
- line = line.rpad(" ", indent - 2) + " ";
+ line = plib::rpad(line, pstring(" "), indent - 2) + " ";
if (line.length() > indent)
{
//ret += "TestGroup abc\n def gef\nxyz\n\n" ;
@@ -250,6 +255,7 @@ namespace plib {
if (grp->help() != "") ret += split_paragraphs(grp->help(), width, 4, 4) + "\n";
}
}
+ // FIXME: other help ...
pstring ex("");
for (auto & optbase : m_opts )
{
@@ -266,22 +272,22 @@ namespace plib {
return ret;
}
- option *options::getopt_short(pstring arg)
+ option *options::getopt_short(const pstring &arg) const
{
for (auto & optbase : m_opts)
{
auto opt = dynamic_cast<option *>(optbase);
- if (opt && opt->short_opt() == arg)
+ if (opt && arg != "" && opt->short_opt() == arg)
return opt;
}
return nullptr;
}
- option *options::getopt_long(pstring arg)
+ option *options::getopt_long(const pstring &arg) const
{
for (auto & optbase : m_opts)
{
auto opt = dynamic_cast<option *>(optbase);
- if (opt && opt->long_opt() == arg)
+ if (opt && arg !="" && opt->long_opt() == arg)
return opt;
}
return nullptr;
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index 491ac0b4d91..086fe32fc8a 100644
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -10,8 +10,8 @@
#ifndef POPTIONS_H_
#define POPTIONS_H_
-#include "pstring.h"
#include "plists.h"
+#include "pstring.h"
#include "putil.h"
namespace plib {
@@ -24,10 +24,12 @@ class options;
class option_base
{
public:
- option_base(options &parent, pstring help);
- virtual ~option_base();
+ option_base(options &parent, const pstring &help);
+ virtual ~option_base() = default;
+
+ COPYASSIGNMOVE(option_base, delete)
- pstring help() { return m_help; }
+ pstring help() const { return m_help; }
private:
pstring m_help;
};
@@ -35,11 +37,10 @@ private:
class option_group : public option_base
{
public:
- option_group(options &parent, pstring group, pstring help)
+ option_group(options &parent, const pstring &group, const pstring &help)
: option_base(parent, help), m_group(group) { }
- ~option_group();
- pstring group() { return m_group; }
+ pstring group() const { return m_group; }
private:
pstring m_group;
};
@@ -47,11 +48,10 @@ private:
class option_example : public option_base
{
public:
- option_example(options &parent, pstring group, pstring help)
+ option_example(options &parent, const pstring &group, const pstring &help)
: option_base(parent, help), m_example(group) { }
- ~option_example();
- pstring example() { return m_example; }
+ pstring example() const { return m_example; }
private:
pstring m_example;
};
@@ -60,8 +60,7 @@ private:
class option : public option_base
{
public:
- option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument);
- ~option();
+ option(options &parent, const pstring &ashort, const pstring &along, const pstring &help, bool has_argument);
/* no_argument options will be called with "" argument */
@@ -89,131 +88,177 @@ private:
class option_str : public option
{
public:
- option_str(options &parent, pstring ashort, pstring along, pstring defval, pstring help)
+ option_str(options &parent, const pstring &ashort, const pstring &along, const pstring &defval, const pstring &help)
: option(parent, ashort, along, help, true), m_val(defval)
{}
- pstring operator ()() { return m_val; }
+ pstring operator ()() const { return m_val; }
protected:
- virtual int parse(const pstring &argument) override;
+ int parse(const pstring &argument) override;
private:
pstring m_val;
};
-class option_str_limit : public option
+class option_str_limit_base : public option
{
public:
- option_str_limit(options &parent, pstring ashort, pstring along, pstring defval, pstring limit, pstring help)
- : option(parent, ashort, along, help, true), m_val(defval)
- , m_limit(plib::psplit(limit, ":"))
+ option_str_limit_base(options &parent, const pstring &ashort, const pstring &along, std::vector<pstring> &&limit, const pstring &help)
+ : option(parent, ashort, along, help, true)
+ , m_limit(limit)
{
}
-
- pstring operator ()() { return m_val; }
- const std::vector<pstring> &limit() { return m_limit; }
+ const std::vector<pstring> &limit() const { return m_limit; }
protected:
- virtual int parse(const pstring &argument) override;
private:
- pstring m_val;
std::vector<pstring> m_limit;
};
-class option_bool : public option
+
+template <typename T>
+class option_str_limit : public option_str_limit_base
{
public:
- option_bool(options &parent, pstring ashort, pstring along, pstring help)
- : option(parent, ashort, along, help, false), m_val(false)
- {}
+ option_str_limit(options &parent, const pstring &ashort, const pstring &along, const T &defval, std::vector<pstring> &&limit, const pstring &help)
+ : option_str_limit_base(parent, ashort, along, std::move(limit), help), m_val(defval)
+ {
+ }
+
+ T operator ()() const { return m_val; }
- bool operator ()() { return m_val; }
+ pstring as_string() const { return limit()[m_val]; }
protected:
- virtual int parse(const pstring &argument) override;
+ int parse(const pstring &argument) override
+ {
+ auto raw = plib::container::indexof(limit(), argument);
+
+ if (raw != plib::container::npos)
+ {
+ m_val = static_cast<T>(raw);
+ return 0;
+ }
+ else
+ return 1;
+ }
private:
- bool m_val;
+ T m_val;
};
-class option_double : public option
+class option_bool : public option
{
public:
- option_double(options &parent, pstring ashort, pstring along, double defval, pstring help)
- : option(parent, ashort, along, help, true), m_val(defval)
+ option_bool(options &parent, const pstring &ashort, const pstring &along, const pstring &help)
+ : option(parent, ashort, along, help, false), m_val(false)
{}
- double operator ()() { return m_val; }
+ bool operator ()() const { return m_val; }
protected:
- virtual int parse(const pstring &argument) override;
+ int parse(const pstring &argument) override;
private:
- double m_val;
+ bool m_val;
};
-class option_long : public option
+template <typename T>
+class option_num : public option
{
public:
- option_long(options &parent, pstring ashort, pstring along, long defval, pstring help)
- : option(parent, ashort, along, help, true), m_val(defval)
+ option_num(options &parent, const pstring &ashort, const pstring &along, T defval,
+ const pstring &help,
+ T minval = std::numeric_limits<T>::min(),
+ T maxval = std::numeric_limits<T>::max() )
+ : option(parent, ashort, along, help, true)
+ , m_val(defval)
+ , m_min(minval)
+ , m_max(maxval)
{}
- long operator ()() { return m_val; }
+ T operator ()() const { return m_val; }
protected:
- virtual int parse(const pstring &argument) override;
+ int parse(const pstring &argument) override
+ {
+ bool err;
+ m_val = pstonum_ne<T>(argument, err);
+ return (err ? 1 : (m_val < m_min || m_val > m_max));
+ }
private:
- long m_val;
+ T m_val;
+ T m_min;
+ T m_max;
};
class option_vec : public option
{
public:
- option_vec(options &parent, pstring ashort, pstring along, pstring help)
+ option_vec(options &parent, const pstring &ashort, const pstring &along, const pstring &help)
: option(parent, ashort, along, help, true)
{}
- std::vector<pstring> operator ()() { return m_val; }
+ const std::vector<pstring> &operator ()() const { return m_val; }
protected:
- virtual int parse(const pstring &argument) override;
+ int parse(const pstring &argument) override;
private:
std::vector<pstring> m_val;
};
-class options
+class option_args : public option_vec
{
public:
+ option_args(options &parent, const pstring &help)
+ : option_vec(parent, "", "", help)
+ {}
+};
- options();
- explicit options(option *o[]);
+class options : public nocopyassignmove
+{
+public:
- ~options();
+ options();
+ explicit options(option **o);
void register_option(option_base *opt);
- int parse(int argc, char *argv[]);
+ int parse(int argc, char **argv);
- pstring help(pstring description, pstring usage,
- unsigned width = 72, unsigned indent = 20);
+ pstring help(const pstring &description, const pstring &usage,
+ unsigned width = 72, unsigned indent = 20) const;
- pstring app() { return m_app; }
+ pstring app() const { return m_app; }
private:
- static pstring split_paragraphs(pstring text, unsigned width, unsigned indent,
+ static pstring split_paragraphs(const pstring &text, unsigned width, unsigned indent,
unsigned firstline_indent);
- option *getopt_short(pstring arg);
- option *getopt_long(pstring arg);
+ void check_consistency();
+
+ template <typename T>
+ T *getopt_type() const
+ {
+ for (auto & optbase : m_opts )
+ {
+ if (auto opt = dynamic_cast<T *>(optbase))
+ return opt;
+ }
+ return nullptr;
+ }
+
+ option *getopt_short(const pstring &arg) const;
+ option *getopt_long(const pstring &arg) const;
std::vector<option_base *> m_opts;
pstring m_app;
+ option_args * m_other_args;
};
-}
+} // namespace plib
#endif /* POPTIONS_H_ */
diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp
index 7547572192d..5e1a231da81 100644
--- a/src/lib/netlist/plib/pparser.cpp
+++ b/src/lib/netlist/plib/pparser.cpp
@@ -16,16 +16,6 @@ namespace plib {
// A simple tokenizer
// ----------------------------------------------------------------------------------------
-ptokenizer::ptokenizer(plib::putf8_reader &strm)
-: m_strm(strm), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"')
-{
-}
-
-ptokenizer::~ptokenizer()
-{
-}
-
-
pstring ptokenizer::currentline_str()
{
return m_cur_line;
@@ -34,7 +24,7 @@ pstring ptokenizer::currentline_str()
void ptokenizer::skipeol()
{
- pstring::code_t c = getc();
+ pstring::value_type c = getc();
while (c)
{
if (c == 10)
@@ -49,11 +39,11 @@ void ptokenizer::skipeol()
}
-pstring::code_t ptokenizer::getc()
+pstring::value_type ptokenizer::getc()
{
if (m_unget != 0)
{
- pstring::code_t c = m_unget;
+ pstring::value_type c = m_unget;
m_unget = 0;
return c;
}
@@ -66,11 +56,11 @@ pstring::code_t ptokenizer::getc()
return 0;
return '\n';
}
- pstring::code_t c = *(m_px++);
+ pstring::value_type c = *(m_px++);
return c;
}
-void ptokenizer::ungetc(pstring::code_t c)
+void ptokenizer::ungetc(pstring::value_type c)
{
m_unget = c;
}
@@ -122,6 +112,7 @@ pstring ptokenizer::get_identifier_or_number()
return tok.str();
}
+// FIXME: combine into template
double ptokenizer::get_number_double()
{
token_t tok = get_token();
@@ -129,8 +120,8 @@ double ptokenizer::get_number_double()
{
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
}
- bool err = false;
- double ret = tok.str().as_double(&err);
+ bool err;
+ auto ret = plib::pstonum_ne<double>(tok.str(), err);
if (err)
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
return ret;
@@ -143,8 +134,8 @@ long ptokenizer::get_number_long()
{
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
}
- bool err = false;
- long ret = tok.str().as_long(&err);
+ bool err;
+ auto ret = plib::pstonum_ne<long>(tok.str(), err);
if (err)
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
return ret;
@@ -182,7 +173,7 @@ ptokenizer::token_t ptokenizer::get_token()
ptokenizer::token_t ptokenizer::get_token_internal()
{
/* skip ws */
- pstring::code_t c = getc();
+ pstring::value_type c = getc();
while (m_whitespace.find(c) != pstring::npos)
{
c = getc();
@@ -272,28 +263,31 @@ void ptokenizer::error(const pstring &errs)
// A simple preprocessor
// ----------------------------------------------------------------------------------------
-ppreprocessor::ppreprocessor(std::vector<define_t> *defines)
-: m_ifflag(0), m_level(0), m_lineno(0)
+ppreprocessor::ppreprocessor(defines_map_type *defines)
+: pistream()
+, m_ifflag(0)
+, m_level(0)
+, m_lineno(0)
+, m_pos(0)
+, m_state(PROCESS)
+, m_comment(false)
{
- m_expr_sep.push_back("!");
- m_expr_sep.push_back("(");
- m_expr_sep.push_back(")");
- m_expr_sep.push_back("+");
- m_expr_sep.push_back("-");
- m_expr_sep.push_back("*");
- m_expr_sep.push_back("/");
- m_expr_sep.push_back("==");
- m_expr_sep.push_back(" ");
- m_expr_sep.push_back("\t");
+ m_expr_sep.emplace_back("!");
+ m_expr_sep.emplace_back("(");
+ m_expr_sep.emplace_back(")");
+ m_expr_sep.emplace_back("+");
+ m_expr_sep.emplace_back("-");
+ m_expr_sep.emplace_back("*");
+ m_expr_sep.emplace_back("/");
+ m_expr_sep.emplace_back("&&");
+ m_expr_sep.emplace_back("||");
+ m_expr_sep.emplace_back("==");
+ m_expr_sep.emplace_back(" ");
+ m_expr_sep.emplace_back("\t");
- m_defines.insert({"__PLIB_PREPROCESSOR__", define_t("__PLIB_PREPROCESSOR__", "1")});
if (defines != nullptr)
- {
- for (auto & p : *defines)
- {
- m_defines.insert({p.m_name, p});
- }
- }
+ m_defines = *defines;
+ m_defines.insert({"__PLIB_PREPROCESSOR__", define_t("__PLIB_PREPROCESSOR__", "1")});
}
void ppreprocessor::error(const pstring &err)
@@ -301,35 +295,42 @@ void ppreprocessor::error(const pstring &err)
throw pexception("PREPRO ERROR: " + err);
}
+pstream::size_type ppreprocessor::vread(value_type *buf, const pstream::size_type n)
+{
+ size_type bytes = std::min(m_buf.size() - m_pos, n);
+
+ if (bytes==0)
+ return 0;
+
+ std::memcpy(buf, m_buf.c_str() + m_pos, bytes);
+ m_pos += bytes;
+ return bytes;
+}
+
+#define CHECKTOK2(p_op, p_prio) \
+ else if (tok == # p_op) \
+ { \
+ if (prio < (p_prio)) \
+ return val; \
+ start++; \
+ const auto v2 = expr(sexpr, start, (p_prio)); \
+ val = (val p_op v2); \
+ } \
+// Operator precedence see https://en.cppreference.com/w/cpp/language/operator_precedence
-double ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio)
+int ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio)
{
- double val;
+ int val = 0;
pstring tok=sexpr[start];
if (tok == "(")
{
start++;
- val = expr(sexpr, start, /*prio*/ 0);
+ val = expr(sexpr, start, /*prio*/ 255);
if (sexpr[start] != ")")
error("parsing error!");
start++;
}
- else if (tok == "!")
- {
- start++;
- val = expr(sexpr, start, 90);
- if (val != 0)
- val = 0;
- else
- val = 1;
- }
- else
- {
- tok=sexpr[start];
- val = tok.as_double();
- start++;
- }
while (start < sexpr.size())
{
tok=sexpr[start];
@@ -338,36 +339,25 @@ double ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start
// FIXME: catch error
return val;
}
- else if (tok == "+")
+ else if (tok == "!")
{
- if (prio > 10)
+ if (prio < 3)
return val;
start++;
- val = val + expr(sexpr, start, 10);
+ val = !expr(sexpr, start, 3);
}
- else if (tok == "-")
- {
- if (prio > 10)
- return val;
- start++;
- val = val - expr(sexpr, start, 10);
- }
- else if (tok == "*")
- {
- start++;
- val = val * expr(sexpr, start, 20);
- }
- else if (tok == "/")
- {
- start++;
- val = val / expr(sexpr, start, 20);
- }
- else if (tok == "==")
+ CHECKTOK2(*, 5)
+ CHECKTOK2(/, 5)
+ CHECKTOK2(+, 6)
+ CHECKTOK2(-, 6)
+ CHECKTOK2(==, 10)
+ CHECKTOK2(&&, 14)
+ CHECKTOK2(||, 15)
+ else
{
- if (prio > 5)
- return val;
+ // FIXME: error handling
+ val = plib::pstonum<decltype(val)>(tok);
start++;
- val = (val == expr(sexpr, start, 5)) ? 1.0 : 0.0;
}
}
return val;
@@ -376,10 +366,7 @@ double ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start
ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
{
auto idx = m_defines.find(name);
- if (idx != m_defines.end())
- return &idx->second;
- else
- return nullptr;
+ return (idx != m_defines.end()) ? &idx->second : nullptr;
}
pstring ppreprocessor::replace_macros(const pstring &line)
@@ -389,78 +376,135 @@ pstring ppreprocessor::replace_macros(const pstring &line)
for (auto & elem : elems)
{
define_t *def = get_define(elem);
- if (def != nullptr)
- ret += def->m_replace;
- else
- ret += elem;
+ ret += (def != nullptr) ? def->m_replace : elem;
}
return ret;
}
-static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, pstring sep)
+static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, const pstring &sep)
{
pstring ret("");
- for (auto & elem : elems)
+ for (std::size_t i = start; i < elems.size(); i++)
{
- ret += elem;
+ ret += elems[i];
ret += sep;
}
return ret;
}
-pstring ppreprocessor::process_line(const pstring &line)
+pstring ppreprocessor::process_comments(pstring line)
+{
+ bool in_string = false;
+
+ std::size_t e = line.size();
+ pstring ret = "";
+ for (std::size_t i=0; i < e; )
+ {
+ pstring c = plib::left(line, 1);
+ line = line.substr(1);
+ if (!m_comment)
+ {
+ if (c=="\"")
+ {
+ in_string = !in_string;
+ ret += c;
+ }
+ else if (in_string && c=="\\")
+ {
+ i++;
+ ret += (c + plib::left(line, 1));
+ line = line.substr(1);
+ }
+ else if (!in_string && c=="/" && plib::left(line,1) == "*")
+ m_comment = true;
+ else if (!in_string && c=="/" && plib::left(line,1) == "/")
+ break;
+ else
+ ret += c;
+ }
+ else
+ if (c=="*" && plib::left(line,1) == "/")
+ {
+ i++;
+ line = line.substr(1);
+ m_comment = false;
+ }
+ i++;
+ }
+ return ret;
+}
+
+pstring ppreprocessor::process_line(pstring line)
{
- pstring lt = line.replace_all("\t"," ").trim();
+ bool line_cont = plib::right(line, 1) == "\\";
+ if (line_cont)
+ line = plib::left(line, line.size() - 1);
+
+ if (m_state == LINE_CONTINUATION)
+ m_line += line;
+ else
+ m_line = line;
+
+ if (line_cont)
+ {
+ m_state = LINE_CONTINUATION;
+ return "";
+ }
+ else
+ m_state = PROCESS;
+
+ line = process_comments(m_line);
+
+ pstring lt = plib::trim(plib::replace_all(line, pstring("\t"), pstring(" ")));
pstring ret;
- m_lineno++;
// FIXME ... revise and extend macro handling
- if (lt.startsWith("#"))
+ if (plib::startsWith(lt, "#"))
{
std::vector<pstring> lti(psplit(lt, " ", true));
- if (lti[0].equals("#if"))
+ if (lti[0] == "#if")
{
m_level++;
std::size_t start = 0;
lt = replace_macros(lt);
- std::vector<pstring> t(psplit(lt.substr(3).replace_all(" ",""), m_expr_sep));
- int val = static_cast<int>(expr(t, start, 0));
+ std::vector<pstring> t(psplit(replace_all(lt.substr(3), pstring(" "), pstring("")), m_expr_sep));
+ auto val = static_cast<int>(expr(t, start, 255));
if (val == 0)
m_ifflag |= (1 << m_level);
}
- else if (lti[0].equals("#ifdef"))
+ else if (lti[0] == "#ifdef")
{
m_level++;
if (get_define(lti[1]) == nullptr)
m_ifflag |= (1 << m_level);
}
- else if (lti[0].equals("#ifndef"))
+ else if (lti[0] == "#ifndef")
{
m_level++;
if (get_define(lti[1]) != nullptr)
m_ifflag |= (1 << m_level);
}
- else if (lti[0].equals("#else"))
+ else if (lti[0] == "#else")
{
m_ifflag ^= (1 << m_level);
}
- else if (lti[0].equals("#endif"))
+ else if (lti[0] == "#endif")
{
m_ifflag &= ~(1 << m_level);
m_level--;
}
- else if (lti[0].equals("#include"))
+ else if (lti[0] == "#include")
{
// ignore
}
- else if (lti[0].equals("#pragma"))
+ else if (lti[0] == "#pragma")
{
- if (m_ifflag == 0 && lti.size() > 3 && lti[1].equals("NETLIST"))
+ if (m_ifflag == 0 && lti.size() > 3 && lti[1] == "NETLIST")
{
- if (lti[2].equals("warning"))
+ if (lti[2] == "warning")
error("NETLIST: " + catremainder(lti, 3, " "));
}
}
- else if (lti[0].equals("#define"))
+ else if (lti[0] == "#define")
{
if (m_ifflag == 0)
{
@@ -470,28 +514,20 @@ pstring ppreprocessor::process_line(const pstring &line)
}
}
else
- error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(line));
+ {
+ if (m_ifflag == 0)
+ error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(replace_macros(line)));
+ }
}
else
{
lt = replace_macros(lt);
if (m_ifflag == 0)
- {
ret += lt;
- }
}
return ret;
}
-void ppreprocessor::process(putf8_reader &istrm, putf8_writer &ostrm)
-{
- pstring line;
- while (istrm.readline(line))
- {
- line = process_line(line);
- ostrm.writeline(line);
- }
-}
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pparser.h b/src/lib/netlist/plib/pparser.h
index 7ec517255c8..1eca20e99ad 100644
--- a/src/lib/netlist/plib/pparser.h
+++ b/src/lib/netlist/plib/pparser.h
@@ -8,20 +8,27 @@
#ifndef PPARSER_H_
#define PPARSER_H_
-#include "pstring.h"
#include "plists.h"
#include "pstream.h"
+#include "pstring.h"
-#include <unordered_map>
#include <cstdint>
+#include <unordered_map>
+
namespace plib {
-class ptokenizer : nocopyassignmove
+class ptokenizer
{
public:
- explicit ptokenizer(plib::putf8_reader &strm);
+ template <typename T>
+ ptokenizer(T &&strm) // NOLINT(misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
+ : m_strm(std::forward<T>(strm)), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"')
+ {
+ }
+
+ COPYASSIGNMOVE(ptokenizer, delete)
- virtual ~ptokenizer();
+ virtual ~ptokenizer() = default;
enum token_type
{
@@ -91,22 +98,23 @@ public:
void require_token(const token_id_t &token_num);
void require_token(const token_t &tok, const token_id_t &token_num);
- token_id_t register_token(pstring token)
+ token_id_t register_token(const pstring &token)
{
token_id_t ret(m_tokens.size());
m_tokens.emplace(token, ret);
return ret;
}
- void set_identifier_chars(pstring s) { m_identifier_chars = s; }
- void set_number_chars(pstring st, pstring rem) { m_number_chars_start = st; m_number_chars = rem; }
- void set_string_char(pstring::code_t c) { m_string = c; }
- void set_whitespace(pstring s) { m_whitespace = s; }
- void set_comment(pstring start, pstring end, pstring line)
+ ptokenizer & identifier_chars(pstring s) { m_identifier_chars = std::move(s); return *this; }
+ ptokenizer & number_chars(pstring st, pstring rem) { m_number_chars_start = std::move(st); m_number_chars = std::move(rem); return *this; }
+ ptokenizer & string_char(pstring::value_type c) { m_string = c; return *this; }
+ ptokenizer & whitespace(pstring s) { m_whitespace = std::move(s); return *this; }
+ ptokenizer & comment(const pstring &start, const pstring &end, const pstring &line)
{
m_tok_comment_start = register_token(start);
m_tok_comment_end = register_token(end);
m_tok_line_comment = register_token(line);
+ return *this;
}
token_t get_token_internal();
@@ -118,17 +126,17 @@ protected:
private:
void skipeol();
- pstring::code_t getc();
- void ungetc(pstring::code_t c);
+ pstring::value_type getc();
+ void ungetc(pstring::value_type c);
bool eof() { return m_strm.eof(); }
- putf8_reader &m_strm;
+ putf8_reader m_strm;
int m_lineno;
pstring m_cur_line;
pstring::const_iterator m_px;
- pstring::code_t m_unget;
+ pstring::value_type m_unget;
/* tokenizer stuff follows ... */
@@ -137,7 +145,7 @@ private:
pstring m_number_chars_start;
std::unordered_map<pstring, token_id_t> m_tokens;
pstring m_whitespace;
- pstring::code_t m_string;
+ pstring::value_type m_string;
token_id_t m_tok_comment_start;
token_id_t m_tok_comment_end;
@@ -145,7 +153,7 @@ private:
};
-class ppreprocessor : plib::nocopyassignmove
+class ppreprocessor : public pistream
{
public:
@@ -158,29 +166,80 @@ public:
pstring m_replace;
};
- explicit ppreprocessor(std::vector<define_t> *defines = nullptr);
- virtual ~ppreprocessor() {}
+ using defines_map_type = std::unordered_map<pstring, define_t>;
+
+ explicit ppreprocessor(defines_map_type *defines = nullptr);
+ ~ppreprocessor() override = default;
+
+ template <typename T>
+ ppreprocessor & process(T &&istrm)
+ {
+ putf8_reader reader(std::forward<T>(istrm));
+ pstring line;
+ while (reader.readline(line))
+ {
+ m_lineno++;
+ line = process_line(line);
+ m_buf += decltype(m_buf)(line.c_str()) + static_cast<char>(10);
+ }
+ return *this;
+ }
+
+ COPYASSIGN(ppreprocessor, delete)
+ ppreprocessor &operator=(ppreprocessor &&src) = delete;
- void process(putf8_reader &istrm, putf8_writer &ostrm);
+
+ ppreprocessor(ppreprocessor &&s) noexcept
+ : m_defines(std::move(s.m_defines))
+ , m_expr_sep(std::move(s.m_expr_sep))
+ , m_ifflag(s.m_ifflag)
+ , m_level(s.m_level)
+ , m_lineno(s.m_lineno)
+ , m_buf(std::move(s.m_buf))
+ , m_pos(s.m_pos)
+ , m_state(s.m_state)
+ , m_comment(s.m_comment)
+ {
+ }
protected:
- double expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio);
+
+ size_type vread(value_type *buf, const size_type n) override;
+ void vseek(const pos_type n) override
+ {
+ plib::unused_var(n);
+ /* FIXME throw exception - should be done in base unless implemented */
+ }
+ pos_type vtell() const override { return m_pos; }
+
+ int expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio);
define_t *get_define(const pstring &name);
pstring replace_macros(const pstring &line);
virtual void error(const pstring &err);
private:
- pstring process_line(const pstring &line);
+ enum state_e
+ {
+ PROCESS,
+ LINE_CONTINUATION
+ };
+ pstring process_line(pstring line);
+ pstring process_comments(pstring line);
- std::unordered_map<pstring, define_t> m_defines;
+ defines_map_type m_defines;
std::vector<pstring> m_expr_sep;
std::uint_least64_t m_ifflag; // 31 if levels
int m_level;
int m_lineno;
+ pstring_t<pu8_traits> m_buf;
+ pos_type m_pos;
+ state_e m_state;
+ pstring m_line;
+ bool m_comment;
};
-}
+} // namespace plib
#endif /* PPARSER_H_ */
diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h
index dc151d5d6a6..9c5329cccde 100644
--- a/src/lib/netlist/plib/ppmf.h
+++ b/src/lib/netlist/plib/ppmf.h
@@ -10,9 +10,8 @@
#include "pconfig.h"
-#include <utility>
#include <cstdint>
-
+#include <utility>
/*
*
@@ -70,7 +69,8 @@ namespace plib {
using generic_function = void (*)();
template<typename MemberFunctionType>
- mfp(MemberFunctionType mftp)
+ mfp(MemberFunctionType mftp) // NOLINT(cppcoreguidelines-pro-type-member-init)
+
: m_function(0), m_this_delta(0), m_size(sizeof(mfp))
{
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
@@ -82,7 +82,7 @@ namespace plib {
mfp mfpo(mftp);
//return mfpo.update_after_bind<FunctionType>(object);
generic_function rfunc(nullptr);
- generic_class *robject = reinterpret_cast<generic_class *>(object);
+ auto robject = reinterpret_cast<generic_class *>(object);
mfpo.convert_to_generic(rfunc, robject);
func = reinterpret_cast<FunctionType>(rfunc);
object = reinterpret_cast<ObjectType *>(robject);
@@ -95,7 +95,8 @@ namespace plib {
if (PHAS_PMF_INTERNAL == 1)
{
// apply the "this" delta to the object first
- generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+ // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
+ auto o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
// if the low bit of the vtable index is clear, then it is just a raw function pointer
if (!(m_function & 1))
@@ -241,23 +242,28 @@ namespace plib {
{
public:
class generic_class;
+
+ template <class C>
+ using MemberFunctionType = R (C::*)(Targs...);
+
pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
- template<typename MemberFunctionType, typename O>
- pmfp(MemberFunctionType mftp, O *object)
+ template<typename O>
+ pmfp(MemberFunctionType<O> mftp, O *object)
: pmfp_base<R, Targs...>()
{
this->set(mftp, object);
}
- template<typename MemberFunctionType, typename O>
- void set(MemberFunctionType mftp, O *object)
+
+ template<typename O>
+ void set(MemberFunctionType<O> mftp, O *object)
{
this->set_base(mftp, object);
m_obj = reinterpret_cast<generic_class *>(object);
}
- inline R operator()(Targs... args)
+ inline R operator()(Targs ... args)
{
return this->call(m_obj, std::forward<Targs>(args)...);
}
@@ -269,6 +275,6 @@ namespace plib {
};
-}
+} // namespace plib
#endif /* PPMF_H_ */
diff --git a/src/lib/netlist/plib/pstate.cpp b/src/lib/netlist/plib/pstate.cpp
index 043033ed1ea..3bd93ed4f8e 100644
--- a/src/lib/netlist/plib/pstate.cpp
+++ b/src/lib/netlist/plib/pstate.cpp
@@ -9,17 +9,6 @@
#include "palloc.h"
namespace plib {
-state_manager_t::state_manager_t()
-{
-}
-
-state_manager_t::~state_manager_t()
-{
- m_save.clear();
- m_custom.clear();
-}
-
-
void state_manager_t::save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr)
{
@@ -29,46 +18,40 @@ void state_manager_t::save_state_ptr(const void *owner, const pstring &stname, c
void state_manager_t::remove_save_items(const void *owner)
{
- for (auto i = m_save.begin(); i != m_save.end(); )
+ auto i = m_save.end();
+ while (i != m_save.begin())
{
+ i--;
if (i->get()->m_owner == owner)
i = m_save.erase(i);
- else
- i++;
}
- for (auto i = m_custom.begin(); i != m_custom.end(); )
+ i = m_custom.end();
+ while (i > m_custom.begin())
{
+ i--;
if (i->get()->m_owner == owner)
i = m_custom.erase(i);
- else
- i++;
}
}
void state_manager_t::pre_save()
{
for (auto & s : m_custom)
- s->m_callback->on_pre_save();
+ s->m_callback->on_pre_save(*this);
}
void state_manager_t::post_load()
{
for (auto & s : m_custom)
- s->m_callback->on_post_load();
+ s->m_callback->on_post_load(*this);
}
template<> void state_manager_t::save_item(const void *owner, callback_t &state, const pstring &stname)
{
- //save_state_ptr(stname, DT_CUSTOM, 0, 1, &state);
callback_t *state_p = &state;
auto p = plib::make_unique<entry_t>(stname, owner, state_p);
m_custom.push_back(std::move(p));
state.register_state(*this, stname);
}
-state_manager_t::callback_t::~callback_t()
-{
-}
-
-
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h
index 9757d6408b7..ac75ca6b69e 100644
--- a/src/lib/netlist/plib/pstate.h
+++ b/src/lib/netlist/plib/pstate.h
@@ -8,11 +8,13 @@
#ifndef PSTATE_H_
#define PSTATE_H_
+#include "palloc.h"
#include "pstring.h"
#include "ptypes.h"
-#include <vector>
+#include <array>
#include <memory>
+#include <vector>
// ----------------------------------------------------------------------------------------
// state saving ...
@@ -38,32 +40,31 @@ public:
const bool is_custom;
};
- template<typename T> struct datatype_f
+ template<typename T>
+ static datatype_t dtype()
{
- static inline const datatype_t f()
- {
- return datatype_t(sizeof(T),
- plib::is_integral<T>::value || std::is_enum<T>::value,
- std::is_floating_point<T>::value);
- }
- };
+ return datatype_t(sizeof(T),
+ plib::is_integral<T>::value || std::is_enum<T>::value,
+ std::is_floating_point<T>::value);
+ }
class callback_t
{
public:
using list_t = std::vector<callback_t *>;
- virtual ~callback_t();
-
virtual void register_state(state_manager_t &manager, const pstring &module) = 0;
- virtual void on_pre_save() = 0;
- virtual void on_post_load() = 0;
+ virtual void on_pre_save(state_manager_t &manager) = 0;
+ virtual void on_post_load(state_manager_t &manager) = 0;
protected:
+ callback_t() = default;
+ ~callback_t() = default;
+ COPYASSIGNMOVE(callback_t, default)
};
struct entry_t
{
- using list_t = std::vector<std::unique_ptr<entry_t>>;
+ using list_t = std::vector<plib::unique_ptr<entry_t>>;
entry_t(const pstring &stname, const datatype_t &dt, const void *owner,
const std::size_t count, void *ptr)
@@ -72,8 +73,6 @@ public:
entry_t(const pstring &stname, const void *owner, callback_t *callback)
: m_name(stname), m_dt(datatype_t(true)), m_owner(owner), m_callback(callback), m_count(0), m_ptr(nullptr) { }
- ~entry_t() { }
-
pstring m_name;
const datatype_t m_dt;
const void * m_owner;
@@ -82,35 +81,49 @@ public:
void * m_ptr;
};
- state_manager_t();
- ~state_manager_t();
+ state_manager_t() = default;
- template<typename C> void save_item(const void *owner, C &state, const pstring &stname)
+ template<typename C>
+ void save_item(const void *owner, C &state, const pstring &stname)
{
- save_state_ptr( owner, stname, datatype_f<C>::f(), 1, &state);
+ save_state_ptr( owner, stname, dtype<C>(), 1, &state);
}
- template<typename C, std::size_t N> void save_item(const void *owner, C (&state)[N], const pstring &stname)
+ template<typename C, std::size_t N>
+ void save_item(const void *owner, C (&state)[N], const pstring &stname) // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
{
- save_state_ptr(owner, stname, datatype_f<C>::f(), N, &(state[0]));
+ save_state_ptr(owner, stname, dtype<C>(), N, &(state[0]));
}
- template<typename C> void save_item(const void *owner, C *state, const pstring &stname, const std::size_t count)
+ template<typename C>
+ void save_item(const void *owner, C *state, const pstring &stname, const std::size_t count)
{
- save_state_ptr(owner, stname, datatype_f<C>::f(), count, state);
+ save_state_ptr(owner, stname, dtype<C>(), count, state);
}
template<typename C>
void save_item(const void *owner, std::vector<C> &v, const pstring &stname)
{
- save_state(v.data(), owner, stname, v.size());
+ save_state_ptr(owner, stname, dtype<C>(), v.size(), v.data());
+ }
+
+ template<typename C, std::size_t N>
+ void save_item(const void *owner, std::array<C, N> &a, const pstring &stname)
+ {
+ save_state_ptr(owner, stname, dtype<C>(), N, a.data());
}
void pre_save();
void post_load();
void remove_save_items(const void *owner);
- const entry_t::list_t &save_list() const { return m_save; }
+ const std::vector<const entry_t *> save_list() const
+ {
+ std::vector<const entry_t *> ret;
+ for (auto &i : m_save)
+ ret.push_back(i.get());
+ return ret;
+ }
void save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr);
@@ -124,6 +137,6 @@ private:
template<> void state_manager_t::save_item(const void *owner, callback_t &state, const pstring &stname);
-}
+} // namespace plib
#endif /* PSTATE_H_ */
diff --git a/src/lib/netlist/plib/pstream.cpp b/src/lib/netlist/plib/pstream.cpp
index 420f63c9e5e..a7acdaafb52 100644
--- a/src/lib/netlist/plib/pstream.cpp
+++ b/src/lib/netlist/plib/pstream.cpp
@@ -8,9 +8,9 @@
#include "pstream.h"
#include "palloc.h"
+#include <algorithm>
#include <cstdio>
#include <cstdlib>
-#include <algorithm>
// VS2015 prefers _dup
#ifdef _WIN32
@@ -21,34 +21,14 @@
namespace plib {
-pstream::~pstream()
-{
-}
-
// -----------------------------------------------------------------------------
// pistream: input stream
// -----------------------------------------------------------------------------
-pistream::~pistream()
-{
-}
-
// -----------------------------------------------------------------------------
// postream: output stream
// -----------------------------------------------------------------------------
-postream::~postream()
-{
-}
-
-void postream::write(pistream &strm)
-{
- char buf[1024];
- pos_type r;
- while ((r=strm.read(buf, 1024)) > 0)
- write(buf, r);
-}
-
// -----------------------------------------------------------------------------
// Input file stream
// -----------------------------------------------------------------------------
@@ -91,7 +71,7 @@ pifilestream::~pifilestream()
}
}
-pifilestream::pos_type pifilestream::vread(void *buf, const pos_type n)
+pifilestream::pos_type pifilestream::vread(value_type *buf, const pos_type n)
{
pos_type r = fread(buf, 1, n, static_cast<FILE *>(m_file));
if (r < n)
@@ -119,7 +99,7 @@ void pifilestream::vseek(const pos_type n)
throw file_e("Generic file operation failed: {}", m_filename);
}
-pifilestream::pos_type pifilestream::vtell()
+pifilestream::pos_type pifilestream::vtell() const
{
long ret = ftell(static_cast<FILE *>(m_file));
if (ret < 0)
@@ -140,10 +120,6 @@ pstdin::pstdin()
/* nothing to do */
}
-pstdin::~pstdin()
-{
-}
-
// -----------------------------------------------------------------------------
// Output file stream
// -----------------------------------------------------------------------------
@@ -180,12 +156,11 @@ pofilestream::~pofilestream()
}
}
-void pofilestream::vwrite(const void *buf, const pos_type n)
+void pofilestream::vwrite(const value_type *buf, const pos_type n)
{
std::size_t r = fwrite(buf, 1, n, static_cast<FILE *>(m_file));
if (r < n)
{
- //printf("%ld %ld %s\n", r, n, strerror(errno));
if (ferror(static_cast<FILE *>(m_file)))
throw file_write_e(m_filename);
}
@@ -204,7 +179,7 @@ void pofilestream::vseek(const pos_type n)
}
}
-pstream::pos_type pofilestream::vtell()
+pstream::pos_type pofilestream::vtell() const
{
std::ptrdiff_t ret = ftell(static_cast<FILE *>(m_file));
if (ret < 0)
@@ -215,11 +190,6 @@ pstream::pos_type pofilestream::vtell()
return static_cast<pos_type>(ret);
}
-postringstream::~postringstream()
-{
-}
-
-
// -----------------------------------------------------------------------------
// pstderr: write to stderr
// -----------------------------------------------------------------------------
@@ -233,10 +203,6 @@ pstderr::pstderr()
{
}
-pstderr::~pstderr()
-{
-}
-
// -----------------------------------------------------------------------------
// pstdout: write to stdout
// -----------------------------------------------------------------------------
@@ -250,35 +216,32 @@ pstdout::pstdout()
{
}
-pstdout::~pstdout()
-{
-}
-
// -----------------------------------------------------------------------------
// Memory stream
// -----------------------------------------------------------------------------
pimemstream::pimemstream(const void *mem, const pos_type len)
- : pistream(FLAG_SEEKABLE), m_pos(0), m_len(len), m_mem(static_cast<const pstring::mem_t *>(mem))
+ : pistream(FLAG_SEEKABLE), m_pos(0), m_len(len), m_mem(static_cast<const char *>(mem))
{
}
-pimemstream::pimemstream(const pomemstream &ostrm)
-: pistream(FLAG_SEEKABLE), m_pos(0), m_len(ostrm.size()), m_mem(reinterpret_cast<pstring::mem_t *>(ostrm.memory()))
+pimemstream::pimemstream()
+ : pistream(FLAG_SEEKABLE), m_pos(0), m_len(0), m_mem(static_cast<const char *>(nullptr))
{
}
-pimemstream::~pimemstream()
+pimemstream::pimemstream(const pomemstream &ostrm)
+: pistream(FLAG_SEEKABLE), m_pos(0), m_len(ostrm.size()), m_mem(reinterpret_cast<const char *>(ostrm.memory()))
{
}
-pimemstream::pos_type pimemstream::vread(void *buf, const pos_type n)
+pimemstream::pos_type pimemstream::vread(value_type *buf, const pos_type n)
{
pos_type ret = (m_pos + n <= m_len) ? n : m_len - m_pos;
if (ret > 0)
{
- std::copy(m_mem + m_pos, m_mem + m_pos + ret, static_cast<char *>(buf));
+ std::copy(m_mem + m_pos, m_mem + m_pos + ret, reinterpret_cast<char *>(buf));
m_pos += ret;
}
@@ -295,78 +258,45 @@ void pimemstream::vseek(const pos_type n)
}
-pimemstream::pos_type pimemstream::vtell()
+pimemstream::pos_type pimemstream::vtell() const
{
return m_pos;
}
-pistringstream::~pistringstream()
-{
-}
-
// -----------------------------------------------------------------------------
// Output memory stream
// -----------------------------------------------------------------------------
pomemstream::pomemstream()
-: postream(FLAG_SEEKABLE), m_pos(0), m_capacity(1024), m_size(0)
-{
- m_mem = palloc_array<char>(m_capacity);
-}
-
-pomemstream::~pomemstream()
+: postream(FLAG_SEEKABLE), m_pos(0), m_mem(1024)
{
- pfree_array(m_mem);
+ m_mem.clear();
}
-void pomemstream::vwrite(const void *buf, const pos_type n)
+void pomemstream::vwrite(const value_type *buf, const pos_type n)
{
- if (m_pos + n >= m_capacity)
- {
- while (m_pos + n >= m_capacity)
- m_capacity *= 2;
- char *o = m_mem;
- m_mem = palloc_array<char>(m_capacity);
- if (m_mem == nullptr)
- {
- throw out_of_mem_e("pomemstream::vwrite");
- }
- std::copy(o, o + m_pos, m_mem);
- pfree_array(o);
- }
+ if (m_pos + n >= m_mem.size())
+ m_mem.resize(m_pos + n);
- std::copy(static_cast<const char *>(buf), static_cast<const char *>(buf) + n, m_mem + m_pos);
+ std::copy(buf, buf + n, &m_mem[0] + m_pos);
m_pos += n;
- m_size = std::max(m_pos, m_size);
}
void pomemstream::vseek(const pos_type n)
{
m_pos = n;
- m_size = std::max(m_pos, m_size);
- if (m_size >= m_capacity)
- {
- while (m_size >= m_capacity)
- m_capacity *= 2;
- char *o = m_mem;
- m_mem = palloc_array<char>(m_capacity);
- if (m_mem == nullptr)
- {
- throw out_of_mem_e("pomemstream::vseek");
- }
- std::copy(o, o + m_pos, m_mem);
- pfree_array(o);
- }
+ if (m_pos>=m_mem.size())
+ m_mem.resize(m_pos);
}
-pstream::pos_type pomemstream::vtell()
+pstream::pos_type pomemstream::vtell() const
{
return m_pos;
}
bool putf8_reader::readline(pstring &line)
{
- pstring::code_t c = 0;
+ putf8string::code_t c = 0;
m_linebuf = "";
if (!this->readcode(c))
{
@@ -378,23 +308,14 @@ bool putf8_reader::readline(pstring &line)
if (c == 10)
break;
else if (c != 13) /* ignore CR */
- m_linebuf += pstring(c);
+ m_linebuf += putf8string(c);
if (!this->readcode(c))
break;
}
- line = m_linebuf;
+ line = m_linebuf.c_str();
return true;
}
-putf8_fmt_writer::putf8_fmt_writer(postream &strm)
-: pfmt_writer_t()
-, putf8_writer(strm)
-{
-}
-
-putf8_fmt_writer::~putf8_fmt_writer()
-{
-}
void putf8_fmt_writer::vdowrite(const pstring &ls) const
{
@@ -403,4 +324,4 @@ void putf8_fmt_writer::vdowrite(const pstring &ls) const
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h
index 3e9ee99cba0..93497eb1423 100644
--- a/src/lib/netlist/plib/pstream.h
+++ b/src/lib/netlist/plib/pstream.h
@@ -7,46 +7,76 @@
#ifndef PSTREAM_H_
#define PSTREAM_H_
+
+#include "palloc.h"
#include "pconfig.h"
-#include "pstring.h"
-#include "pfmtlog.h"
#include "pexception.h"
+#include "pfmtlog.h"
+#include "pstring.h"
+
+#define USE_CSTREAM (0)
+#include <array>
+#include <type_traits>
#include <vector>
+#if USE_CSTREAM
+#include <fstream>
+//#include <strstream>
+#include <sstream>
+#endif
+
namespace plib {
+
+#if USE_CSTREAM
+typedef std::ostream postream;
+typedef std::ofstream pofilestream;
+typedef std::ostringstream postringstream;
+typedef std::ostringstream pomemstream;
+
+#endif
+
// -----------------------------------------------------------------------------
// pstream: things common to all streams
// -----------------------------------------------------------------------------
-class pstream : nocopyassignmove
+class pstream
{
public:
using pos_type = std::size_t;
+ using size_type = std::size_t;
static constexpr pos_type SEEK_EOF = static_cast<pos_type>(-1);
+ COPYASSIGN(pstream, delete)
+ pstream &operator=(pstream &&) noexcept = delete;
+
bool seekable() const { return ((m_flags & FLAG_SEEKABLE) != 0); }
- void seek(const pos_type n)
+ void seekp(const pos_type n)
{
- return vseek(n);
+ vseek(n);
}
- pos_type tell()
+ pos_type tellp() const
{
return vtell();
}
protected:
+ pstream() : m_flags(0)
+ {
+ }
explicit pstream(const unsigned flags) : m_flags(flags)
{
}
- ~pstream();
+ pstream(pstream &&src) noexcept = default;
+
+ virtual ~pstream() = default;
virtual void vseek(const pos_type n) = 0;
- virtual pos_type vtell() = 0;
+ virtual pos_type vtell() const = 0;
static constexpr unsigned FLAG_EOF = 0x01;
static constexpr unsigned FLAG_SEEKABLE = 0x04;
@@ -69,51 +99,71 @@ private:
// pistream: input stream
// -----------------------------------------------------------------------------
-class pistream : public pstream
+template <typename T>
+class pistream_base : public pstream
{
public:
- virtual ~pistream();
+ using value_type = T;
+
+ ~pistream_base() noexcept override = default;
+
+ COPYASSIGN(pistream_base, delete)
+ pistream_base &operator=(pistream_base &&src) noexcept = delete;
bool eof() const { return ((flags() & FLAG_EOF) != 0); }
- pos_type read(void *buf, const pos_type n)
+ pos_type read(T *buf, const pos_type n)
{
return vread(buf, n);
}
protected:
- explicit pistream(const unsigned flags) : pstream(flags) {}
- /* read up to n bytes from stream */
- virtual pos_type vread(void *buf, const pos_type n) = 0;
+ pistream_base() : pstream(0) {}
+ explicit pistream_base(const unsigned flags) : pstream(flags) {}
+ pistream_base(pistream_base &&src) noexcept : pstream(std::move(src)) {}
+ /* read up to n bytes from stream */
+ virtual size_type vread(T *buf, const size_type n) = 0;
};
+using pistream = pistream_base<char>;
+
// -----------------------------------------------------------------------------
// postream: output stream
// -----------------------------------------------------------------------------
-class postream : public pstream
+#if !USE_CSTREAM
+template <typename T>
+class postream_base : public pstream
{
public:
- virtual ~postream();
+ using value_type = T;
+
+ postream_base() = default;
+ ~postream_base() noexcept override = default;
+
+ COPYASSIGN(postream_base, delete)
+ postream_base &operator=(postream_base &&src) noexcept = delete;
- void write(const void *buf, const pos_type n)
+ void write(const T *buf, const size_type n)
{
vwrite(buf, n);
}
- void write(pistream &strm);
-
protected:
- explicit postream(unsigned flags) : pstream(flags) {}
+ explicit postream_base(unsigned flags) : pstream(flags) {}
+ postream_base(postream_base &&src) noexcept : pstream(std::move(src)) {}
+
/* write n bytes to stream */
- virtual void vwrite(const void *buf, const pos_type n) = 0;
+ virtual void vwrite(const T *buf, const size_type n) = 0;
private:
};
+using postream = postream_base<char>;
+
// -----------------------------------------------------------------------------
// pomemstream: output string stream
// -----------------------------------------------------------------------------
@@ -123,22 +173,31 @@ class pomemstream : public postream
public:
pomemstream();
- virtual ~pomemstream() override;
- char *memory() const { return m_mem; }
- pos_type size() const { return m_size; }
+ COPYASSIGN(pomemstream, delete)
+
+ pomemstream(pomemstream &&src) noexcept
+ : postream(std::move(src))
+ , m_pos(src.m_pos)
+ , m_mem(std::move(src.m_mem))
+ {
+ }
+ pomemstream &operator=(pomemstream &&src) = delete;
+
+ ~pomemstream() override = default;
+
+ const char *memory() const { return m_mem.data(); }
+ pos_type size() const { return m_mem.size(); }
protected:
/* write n bytes to stream */
- virtual void vwrite(const void *buf, const pos_type) override;
- virtual void vseek(const pos_type n) override;
- virtual pos_type vtell() override;
+ void vwrite(const value_type *buf, const pos_type) override;
+ void vseek(const pos_type n) override;
+ pos_type vtell() const override;
private:
pos_type m_pos;
- pos_type m_capacity;
- pos_type m_size;
- char *m_mem;
+ std::vector<char> m_mem;
};
class postringstream : public postream
@@ -146,18 +205,26 @@ class postringstream : public postream
public:
postringstream() : postream(0) { }
- virtual ~postringstream() override;
+ postringstream(postringstream &&src) noexcept
+ : postream(std::move(src))
+ , m_buf(std::move(src.m_buf))
+ { src.m_buf = ""; }
+
+ COPYASSIGN(postringstream, delete)
+ postringstream &operator=(postringstream &&src) = delete;
+
+ ~postringstream() override = default;
const pstring &str() { return m_buf; }
protected:
/* write n bytes to stream */
- virtual void vwrite(const void *buf, const pos_type n) override
+ void vwrite(const value_type *buf, const pos_type n) override
{
- m_buf += pstring(static_cast<const pstring::mem_t *>(buf), n, pstring::UTF8);
+ m_buf += pstring(reinterpret_cast<const pstring::mem_t *>(buf), n);
}
- virtual void vseek(const pos_type n) override { }
- virtual pos_type vtell() override { return m_buf.mem_t_size(); }
+ void vseek(const pos_type n) override { unused_var(n); }
+ pos_type vtell() const override { return m_buf.size(); }
private:
pstring m_buf;
@@ -171,15 +238,28 @@ class pofilestream : public postream
{
public:
- explicit pofilestream(const pstring &fname);
- virtual ~pofilestream() override;
+ pofilestream(const pstring &fname);
+ pofilestream(pofilestream &&src) noexcept
+ : postream(std::move(src))
+ , m_file(src.m_file)
+ , m_pos(src.m_pos)
+ , m_actually_close(src.m_actually_close)
+ , m_filename(std::move(src.m_filename))
+ {
+ src.m_file = nullptr;
+ src.m_actually_close = false;
+ }
+ COPYASSIGN(pofilestream, delete)
+ pofilestream &operator=(pofilestream &&src) = delete;
+
+ ~pofilestream() override;
protected:
pofilestream(void *file, const pstring &name, const bool do_close);
/* write n bytes to stream */
- virtual void vwrite(const void *buf, const pos_type n) override;
- virtual void vseek(const pos_type n) override;
- virtual pos_type vtell() override;
+ void vwrite(const value_type *buf, const pos_type n) override;
+ void vseek(const pos_type n) override;
+ pos_type vtell() const override;
private:
void *m_file;
@@ -193,12 +273,17 @@ private:
// -----------------------------------------------------------------------------
// pstderr: write to stderr
// -----------------------------------------------------------------------------
+#endif
class pstderr : public pofilestream
{
public:
pstderr();
- virtual ~pstderr();
+ pstderr(pstderr &&src) noexcept = default;
+ pstderr &operator=(pstderr &&src) = delete;
+ COPYASSIGN(pstderr, delete)
+
+ ~pstderr() noexcept override= default;
};
// -----------------------------------------------------------------------------
@@ -209,7 +294,11 @@ class pstdout : public pofilestream
{
public:
pstdout();
- virtual ~pstdout();
+ pstdout(pstdout &&src) noexcept = default;
+ pstdout &operator=(pstdout &&src) = delete;
+ COPYASSIGN(pstdout, delete)
+
+ ~pstdout() noexcept override = default;
};
// -----------------------------------------------------------------------------
@@ -220,16 +309,29 @@ class pifilestream : public pistream
{
public:
- explicit pifilestream(const pstring &fname);
- virtual ~pifilestream() override;
+ pifilestream(const pstring &fname);
+ ~pifilestream() override;
+
+ pifilestream(pifilestream &&src) noexcept
+ : pistream(std::move(src))
+ , m_file(src.m_file)
+ , m_pos(src.m_pos)
+ , m_actually_close(src.m_actually_close)
+ , m_filename(std::move(src.m_filename))
+ {
+ src.m_actually_close = false;
+ src.m_file = nullptr;
+ }
+ COPYASSIGN(pifilestream, delete)
+ pifilestream &operator=(pifilestream &&src) = delete;
protected:
pifilestream(void *file, const pstring &name, const bool do_close);
/* read up to n bytes from stream */
- virtual pos_type vread(void *buf, const pos_type n) override;
- virtual void vseek(const pos_type n) override;
- virtual pos_type vtell() override;
+ pos_type vread(value_type *buf, const pos_type n) override;
+ void vseek(const pos_type n) override;
+ pos_type vtell() const override;
private:
void *m_file;
@@ -249,7 +351,10 @@ class pstdin : public pifilestream
public:
pstdin();
- virtual ~pstdin() override;
+ pstdin(pstdin &&src) noexcept = default;
+ pstdin &operator=(pstdin &&src) = delete;
+ COPYASSIGN(pstdin, delete)
+ ~pstdin() override = default;
};
// -----------------------------------------------------------------------------
@@ -261,15 +366,36 @@ class pimemstream : public pistream
public:
pimemstream(const void *mem, const pos_type len);
+ pimemstream();
+
+ pimemstream(pimemstream &&src) noexcept
+ : pistream(std::move(src))
+ , m_pos(src.m_pos)
+ , m_len(src.m_len)
+ , m_mem(src.m_mem)
+ {
+ src.m_mem = nullptr;
+ }
+ COPYASSIGN(pimemstream, delete)
+ pimemstream &operator=(pimemstream &&src) = delete;
+
explicit pimemstream(const pomemstream &ostrm);
- virtual ~pimemstream() override;
+
+ ~pimemstream() override = default;
pos_type size() const { return m_len; }
protected:
+
+ void set_mem(const void *mem, const pos_type len)
+ {
+ m_mem = static_cast<const char *>(mem);
+ m_len = len;
+ }
+
/* read up to n bytes from stream */
- virtual pos_type vread(void *buf, const pos_type n) override;
- virtual void vseek(const pos_type n) override;
- virtual pos_type vtell() override;
+ pos_type vread(value_type *buf, const pos_type n) override;
+ void vseek(const pos_type n) override;
+ pos_type vtell() const override;
private:
pos_type m_pos;
@@ -284,12 +410,25 @@ private:
class pistringstream : public pimemstream
{
public:
- explicit pistringstream(const pstring &str) : pimemstream(str.c_str(), str.mem_t_size()), m_str(str) { }
- virtual ~pistringstream() override;
+ pistringstream(const pstring &str)
+ : pimemstream()
+ , m_str(str)
+ {
+ set_mem(m_str.c_str(), std::strlen(m_str.c_str()));
+ }
+ pistringstream(pistringstream &&src) noexcept
+ : pimemstream(std::move(src)), m_str(src.m_str)
+ {
+ set_mem(m_str.c_str(), std::strlen(m_str.c_str()));
+ }
+ COPYASSIGN(pistringstream, delete)
+ pistringstream &operator=(pistringstream &&src) = delete;
+
+ ~pistringstream() override = default;
private:
/* only needed for a reference till destruction */
- pstring m_str;
+ const pstring m_str;
};
// -----------------------------------------------------------------------------
@@ -298,47 +437,84 @@ private:
/* this digests linux & dos/windows text files */
-class putf8_reader : plib::nocopyassignmove
+
+template <typename T>
+struct constructor_helper
+{
+ plib::unique_ptr<pistream> operator()(T &&s) { return std::move(plib::make_unique<T>(std::move(s))); }
+};
+
+// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
+class putf8_reader
{
public:
- explicit putf8_reader(pistream &strm) : m_strm(strm) {}
- virtual ~putf8_reader() {}
- bool eof() const { return m_strm.eof(); }
+ COPYASSIGN(putf8_reader, delete)
+ putf8_reader &operator=(putf8_reader &&src) = delete;
+ virtual ~putf8_reader() = default;
+
+ template <typename T>
+ friend struct constructor_helper;
+
+ template <typename T>
+ putf8_reader(T &&strm) // NOLINT(cppcoreguidelines-special-member-functions, misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
+ : m_strm(std::move(constructor_helper<T>()(std::move(strm)))) // NOLINT(bugprone-move-forwarding-reference)
+ {}
+
+ bool eof() const { return m_strm->eof(); }
bool readline(pstring &line);
- bool readbyte1(char &b)
+ bool readbyte1(pistream::value_type &b)
{
- return (m_strm.read(&b, 1) == 1);
+ return (m_strm->read(&b, 1) == 1);
}
- bool readcode(pstring::code_t &c)
+ bool readcode(putf8string::traits_type::code_t &c)
{
- char b[4];
- if (m_strm.read(&b[0], 1) != 1)
+ std::array<pistream::value_type, 4> b{0};
+ if (m_strm->read(&b[0], 1) != 1)
return false;
- const std::size_t l = pstring::traits_type::codelen(b);
+ const std::size_t l = putf8string::traits_type::codelen(reinterpret_cast<putf8string::traits_type::mem_t *>(&b));
for (std::size_t i = 1; i < l; i++)
- if (m_strm.read(&b[i], 1) != 1)
+ if (m_strm->read(&b[i], 1) != 1)
return false;
- c = pstring::traits_type::code(b);
+ c = putf8string::traits_type::code(reinterpret_cast<putf8string::traits_type::mem_t *>(&b));
return true;
}
private:
- pistream &m_strm;
- pstring m_linebuf;
+ plib::unique_ptr<pistream> m_strm;
+ putf8string m_linebuf;
};
+template <>
+struct constructor_helper<putf8_reader>
+{
+ plib::unique_ptr<pistream> operator()(putf8_reader &&s) { return std::move(s.m_strm); }
+};
+
+template <>
+struct constructor_helper<plib::unique_ptr<pistream>>
+{
+ plib::unique_ptr<pistream> operator()(plib::unique_ptr<pistream> &&s) { return std::move(s); }
+};
+
+
// -----------------------------------------------------------------------------
// putf8writer_t: writer on top of ostream
// -----------------------------------------------------------------------------
-class putf8_writer : plib::nocopyassignmove
+class putf8_writer
{
public:
- explicit putf8_writer(postream &strm) : m_strm(strm) {}
- virtual ~putf8_writer() {}
+ explicit putf8_writer(postream *strm) : m_strm(strm) {}
+
+ putf8_writer(putf8_writer &&src) noexcept : m_strm(src.m_strm) {}
+
+ COPYASSIGN(putf8_writer, delete)
+ putf8_writer &operator=(putf8_writer &&src) = delete;
+
+ virtual ~putf8_writer() = default;
void writeline(const pstring &line) const
{
@@ -348,24 +524,34 @@ public:
void write(const pstring &text) const
{
- m_strm.write(text.c_str(), text.mem_t_size());
+ // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
+ const putf8string conv_utf8(text);
+ m_strm->write(reinterpret_cast<const pistream::value_type *>(conv_utf8.c_str()), conv_utf8.mem_t_size());
}
- void write(const pstring::code_t c) const
+ void write(const pstring::value_type c) const
{
- write(pstring(c));
+ pstring t = pstring("") + c;
+ write(t);
}
private:
- postream &m_strm;
+ postream *m_strm;
};
class putf8_fmt_writer : public pfmt_writer_t<putf8_fmt_writer>, public putf8_writer
{
public:
- explicit putf8_fmt_writer(postream &strm);
- virtual ~putf8_fmt_writer() override;
+ explicit putf8_fmt_writer(postream *strm)
+ : pfmt_writer_t()
+ , putf8_writer(strm)
+ {
+ }
+
+ COPYASSIGNMOVE(putf8_fmt_writer, delete)
+
+ ~putf8_fmt_writer() override = default;
//protected:
void vdowrite(const pstring &ls) const;
@@ -377,22 +563,29 @@ private:
// pbinary_writer_t: writer on top of ostream
// -----------------------------------------------------------------------------
-class pbinary_writer : plib::nocopyassignmove
+class pbinary_writer
{
public:
explicit pbinary_writer(postream &strm) : m_strm(strm) {}
- virtual ~pbinary_writer() {}
+ pbinary_writer(pbinary_writer &&src) noexcept : m_strm(src.m_strm) {}
+
+ COPYASSIGN(pbinary_writer, delete)
+ postringstream &operator=(pbinary_writer &&src) = delete;
+
+ virtual ~pbinary_writer() = default;
template <typename T>
- void write(const T val)
+ void write(const T &val)
{
- m_strm.write(&val, sizeof(T));
+ m_strm.write(reinterpret_cast<const postream::value_type *>(&val), sizeof(T));
}
void write(const pstring &s)
{
- write(s.mem_t_size());
- m_strm.write(s.c_str(), s.mem_t_size());
+ const auto sm = reinterpret_cast<const postream::value_type *>(s.c_str());
+ const std::size_t sl = std::strlen(s.c_str());
+ write(sl);
+ m_strm.write(sm, sl);
}
template <typename T>
@@ -400,34 +593,38 @@ public:
{
std::size_t sz = val.size();
write(sz);
- m_strm.write(val.data(), sizeof(T) * sz);
+ m_strm.write(reinterpret_cast<const postream::value_type *>(val.data()), sizeof(T) * sz);
}
private:
postream &m_strm;
};
-class pbinary_reader : plib::nocopyassignmove
+class pbinary_reader
{
public:
explicit pbinary_reader(pistream &strm) : m_strm(strm) {}
- virtual ~pbinary_reader() {}
+ pbinary_reader(pbinary_reader &&src) noexcept : m_strm(src.m_strm) { }
+
+ COPYASSIGN(pbinary_reader, delete)
+ pbinary_reader &operator=(pbinary_reader &&src) = delete;
+
+ virtual ~pbinary_reader() = default;
template <typename T>
void read(T &val)
{
- m_strm.read(&val, sizeof(T));
+ m_strm.read(reinterpret_cast<pistream::value_type *>(&val), sizeof(T));
}
void read( pstring &s)
{
std::size_t sz = 0;
read(sz);
- pstring::mem_t *buf = new pstring::mem_t[sz+1];
- m_strm.read(buf, sz);
+ std::vector<plib::string_info<pstring>::mem_t> buf(sz+1);
+ m_strm.read(buf.data(), sz);
buf[sz] = 0;
- s = pstring(buf, pstring::UTF8);
- delete [] buf;
+ s = pstring(buf.data());
}
template <typename T>
@@ -436,13 +633,38 @@ public:
std::size_t sz = 0;
read(sz);
val.resize(sz);
- m_strm.read(val.data(), sizeof(T) * sz);
+ m_strm.read(reinterpret_cast<pistream::value_type *>(val.data()), sizeof(T) * sz);
}
private:
pistream &m_strm;
};
+inline void copystream(postream &dest, pistream &src)
+{
+ std::array<postream::value_type, 1024> buf; // NOLINT(cppcoreguidelines-pro-type-member-init)
+ pstream::pos_type r;
+ while ((r=src.read(buf.data(), 1024)) > 0)
+ dest.write(buf.data(), r);
}
+struct perrlogger
+{
+ template <typename ... Args>
+ explicit perrlogger(Args&& ... args)
+ {
+ h()(std::forward<Args>(args)...);
+ }
+private:
+ static putf8_fmt_writer &h()
+ {
+ static plib::pstderr perr_strm;
+ static plib::putf8_fmt_writer perr(&perr_strm);
+ return perr;
+ }
+};
+
+
+} // namespace plib
+
#endif /* PSTREAM_H_ */
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index 47d35d7c82f..c304f11d1fd 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -10,17 +10,8 @@
#include "plists.h"
#include <algorithm>
-#include <stack>
#include <atomic>
-
-template <typename T>
-std::size_t strlen_mem(const T *s)
-{
- std::size_t len(0);
- while (*s++)
- ++len;
- return len;
-}
+#include <stack>
template<typename F>
int pstring_t<F>::compare(const pstring_t &right) const
@@ -67,18 +58,6 @@ pstring_t<F> pstring_t<F>::substr(size_type start, size_type nlen) const
}
template<typename F>
-pstring_t<F> pstring_t<F>::ucase() const
-{
- pstring_t ret;
- for (const auto &c : *this)
- if (c >= 'a' && c <= 'z')
- ret += (c - 'a' + 'A');
- else
- ret += c;
- return ret;
-}
-
-template<typename F>
typename pstring_t<F>::size_type pstring_t<F>::find_first_not_of(const pstring_t &no) const
{
size_type pos = 0;
@@ -150,114 +129,6 @@ typename pstring_t<F>::size_type pstring_t<F>::find(code_t search, size_type sta
return find(ss, start);
}
-
-template<typename F>
-pstring_t<F> pstring_t<F>::replace_all(const pstring_t &search, const pstring_t &replace) const
-{
- pstring_t ret;
- const size_type slen = search.length();
-
- size_type last_s = 0;
- size_type s = find(search, last_s);
- while (s != npos)
- {
- ret += substr(last_s, s - last_s);
- ret += replace;
- last_s = s + slen;
- s = find(search, last_s);
- }
- ret += substr(last_s);
- return ret;
-}
-
-template<typename F>
-pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const size_type cnt) const
-{
- // FIXME: pstringbuffer ret(*this);
-
- pstring_t ret(*this);
- size_type wsl = ws.length();
- for (auto i = ret.length(); i < cnt; i+=wsl)
- ret += ws;
- return ret;
-}
-
-static double pstod(const pstring_t<pu8_traits> &str, std::size_t *e)
-{
- return std::stod(str.cpp_string(), e);
-}
-
-static double pstod(const pstring &str, std::size_t *e)
-{
- return std::stod(str.cpp_string(), e);
-}
-
-static double pstod(const pwstring &str, std::size_t *e)
-{
- return std::stod(str.cpp_string(), e);
-}
-
-static double pstod(const pu16string &str, std::size_t *e)
-{
- pstring c;
- c = str;
- return std::stod(c.cpp_string(), e);
-}
-
-static long pstol(const pstring_t<pu8_traits> &str, std::size_t *e, int base = 10)
-{
- return std::stol(str.cpp_string(), e, base);
-}
-
-static long pstol(const pstring &str, std::size_t *e, int base = 10)
-{
- return std::stol(str.cpp_string(), e, base);
-}
-
-static long pstol(const pwstring &str, std::size_t *e, int base = 10)
-{
- return std::stol(str.cpp_string(), e, base);
-}
-
-static long pstol(const pu16string &str, std::size_t *e, int base = 10)
-{
- pstring c;
- c = str;
- return std::stol(c.cpp_string(), e, base);
-}
-
-template<typename F>
-double pstring_t<F>::as_double(bool *error) const
-{
- std::size_t e = 0;
- if (error != nullptr)
- *error = false;
- double ret = pstod(*this, &e);
- if (e != mem_t_size())
- if (error != nullptr)
- *error = true;
- return ret;
-}
-
-template<typename F>
-long pstring_t<F>::as_long(bool *error) const
-{
- static pstring_t prefix(pstring("0x"));
- long ret;
- std::size_t e = 0;
-
- if (error != nullptr)
- *error = false;
- if (startsWith(prefix))
- ret = pstol(substr(2), &e, 16);
- else
- ret = pstol(*this, &e, 10);
- if (e != mem_t_size())
- if (error != nullptr)
- *error = true;
- return ret;
-}
-
// ----------------------------------------------------------------------------------------
// template stuff ...
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index cabce0e7b93..c4caeab8e8f 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -7,45 +7,50 @@
#ifndef PSTRING_H_
#define PSTRING_H_
-#include <iterator>
+#include "ptypes.h"
+
+#include <cstring>
#include <exception>
+#include <iterator>
+#include <limits>
+#include <stdexcept>
#include <string>
+#include <type_traits>
// ----------------------------------------------------------------------------------------
// pstring: semi-immutable strings ...
//
// The only reason this class exists is the absence of support for multi-byte
-// strings in std:: which I would consider usuable for the use-cases I encounter.
+// strings in std:: which I would consider sub-optimal for the use-cases I encounter.
// ----------------------------------------------------------------------------------------
+// enable this to use std::string instead of pstring globally.
+
+#define PSTRING_USE_STD_STRING (0)
+
template <typename T>
class pstring_const_iterator final
{
public:
- typedef typename T::ref_value_type value_type;
+ using value_type = typename T::ref_value_type;
- typedef value_type const *pointer;
- typedef value_type const &reference;
- typedef std::ptrdiff_t difference_type;
- typedef std::forward_iterator_tag iterator_category;
- typedef typename T::string_type string_type;
- typedef typename T::traits_type traits_type;
+ using pointer = value_type const *;
+ using reference = value_type const &;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
+ using string_type = typename T::string_type;
+ using traits_type = typename T::traits_type;
- pstring_const_iterator() noexcept : p() { }
+ constexpr pstring_const_iterator() noexcept : p() { }
explicit constexpr pstring_const_iterator(const typename string_type::const_iterator &x) noexcept : p(x) { }
-#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (0 == _ITERATOR_DEBUG_LEVEL) // debug iterators are broken
- pstring_const_iterator(const pstring_const_iterator &rhs) noexcept = default;
- pstring_const_iterator(pstring_const_iterator &&rhs) noexcept = default;
- pstring_const_iterator &operator=(const pstring_const_iterator &rhs) noexcept = default;
- pstring_const_iterator &operator=(pstring_const_iterator &&rhs) noexcept = default;
-#endif
pstring_const_iterator& operator++() noexcept { p += static_cast<difference_type>(traits_type::codelen(&(*p))); return *this; }
- pstring_const_iterator operator++(int) noexcept { pstring_const_iterator tmp(*this); operator++(); return tmp; }
+ // NOLINTNEXTLINE(cert-dcl21-cpp)
+ pstring_const_iterator operator++(int) & noexcept { pstring_const_iterator tmp(*this); operator++(); return tmp; }
- bool operator==(const pstring_const_iterator& rhs) const noexcept { return p == rhs.p; }
- bool operator!=(const pstring_const_iterator& rhs) const noexcept { return p != rhs.p; }
+ constexpr bool operator==(const pstring_const_iterator& rhs) const noexcept { return p == rhs.p; }
+ constexpr bool operator!=(const pstring_const_iterator& rhs) const noexcept { return p != rhs.p; }
reference operator*() const noexcept { return *reinterpret_cast<pointer>(&(*p)); }
pointer operator->() const noexcept { return reinterpret_cast<pointer>(&(*p)); }
@@ -60,18 +65,21 @@ template <typename F>
struct pstring_t
{
public:
- typedef F traits_type;
+ using traits_type = F;
- typedef typename traits_type::mem_t mem_t;
- typedef typename traits_type::code_t code_t;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
- typedef typename traits_type::string_type string_type;
+ using mem_t = typename traits_type::mem_t;
+ using code_t = typename traits_type::code_t;
+ using value_type = typename traits_type::code_t;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+ using string_type = typename traits_type::string_type;
- class ref_value_type final
+ // FIXME: this is ugly
+ struct ref_value_type final
{
public:
ref_value_type() = delete;
+ ~ref_value_type() = delete;
ref_value_type(const ref_value_type &) = delete;
ref_value_type(ref_value_type &&) = delete;
ref_value_type &operator=(const ref_value_type &) = delete;
@@ -80,37 +88,27 @@ public:
private:
const mem_t m;
};
- typedef const ref_value_type& const_reference;
- typedef const_reference reference;
-
- enum enc_t
- {
- UTF8,
- UTF16
- };
+ using const_reference = const ref_value_type &;
+ using reference = const_reference;
// simple construction/destruction
- pstring_t()
- {
- }
- ~pstring_t()
- {
- }
+ pstring_t() = default;
+ ~pstring_t() noexcept = default;
// FIXME: Do something with encoding
- pstring_t(const mem_t *string, const enc_t enc)
+ pstring_t(const mem_t *string)
: m_str(string)
{
}
- pstring_t(const mem_t *string, const size_type len, const enc_t enc)
+ pstring_t(const mem_t *string, const size_type len)
: m_str(string, len)
{
}
template<typename C, std::size_t N,
class = typename std::enable_if<std::is_same<C, const mem_t>::value>::type>
- pstring_t(C (&string)[N])
+ pstring_t(C (&string)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
{
static_assert(N > 0,"pstring from array of length 0");
if (string[N-1] != 0)
@@ -118,17 +116,15 @@ public:
m_str.assign(string, N - 1);
}
- pstring_t(const pstring_t &string)
- : m_str(string.m_str)
- { }
- explicit pstring_t(const string_type &string, const enc_t enc)
+ explicit pstring_t(const string_type &string)
: m_str(string)
{ }
- pstring_t(pstring_t &&string)
- : m_str(string.m_str)
- { }
+ pstring_t(const pstring_t &string) = default;
+ pstring_t(pstring_t &&string) noexcept = default;
+ pstring_t &operator=(const pstring_t &string) = default;
+ pstring_t &operator=(pstring_t &&string) noexcept = default;
explicit pstring_t(code_t code)
{
@@ -144,7 +140,8 @@ public:
*this += static_cast<code_t>(c); // FIXME: codepage conversion for u8
}
- pstring_t &operator=(const pstring_t &string) { m_str = string.m_str; return *this; }
+ operator string_type () const { return m_str; }
+
template <typename T,
class = typename std::enable_if<!std::is_same<T, pstring_t::traits_type>::value>::type>
@@ -157,8 +154,8 @@ public:
}
// no non-const const_iterator for now
- typedef pstring_const_iterator<pstring_t> iterator;
- typedef pstring_const_iterator<pstring_t> const_iterator;
+ using iterator = pstring_const_iterator<pstring_t<F> >;
+ using const_iterator = pstring_const_iterator<pstring_t<F> >;
iterator begin() { return iterator(m_str.begin()); }
iterator end() { return iterator(m_str.end()); }
@@ -201,67 +198,26 @@ public:
const_reference at(const size_type pos) const { return *reinterpret_cast<const ref_value_type *>(F::nthcode(m_str.c_str(),pos)); }
- /* The following is not compatible to std::string */
-
- bool equals(const pstring_t &string) const { return (compare(string) == 0); }
-
- bool startsWith(const pstring_t &arg) const { return arg.mem_t_size() > mem_t_size() ? false : m_str.compare(0, arg.mem_t_size(), arg.m_str) == 0; }
- bool endsWith(const pstring_t &arg) const { return arg.mem_t_size() > mem_t_size() ? false : m_str.compare(mem_t_size()-arg.mem_t_size(), arg.mem_t_size(), arg.m_str) == 0; }
-
- pstring_t replace_all(const pstring_t &search, const pstring_t &replace) const;
- pstring_t cat(const pstring_t &s) const { return *this + s; }
- pstring_t cat(code_t c) const { return *this + c; }
-
- // conversions
-
- double as_double(bool *error = nullptr) const;
- long as_long(bool *error = nullptr) const;
-
/* the following are extensions to <string> */
size_type mem_t_size() const { return m_str.size(); }
- pstring_t left(size_type len) const { return substr(0, len); }
- pstring_t right(size_type nlen) const
- {
- return nlen >= length() ? *this : substr(length() - nlen, nlen);
- }
-
- pstring_t ltrim(const pstring_t &ws = pstring_t(" \t\n\r")) const
- {
- return substr(find_first_not_of(ws));
- }
-
- pstring_t rtrim(const pstring_t &ws = pstring_t(" \t\n\r")) const
- {
- auto f = find_last_not_of(ws);
- return f == npos ? pstring_t() : substr(0, f + 1);
- }
-
- pstring_t trim(const pstring_t &ws = pstring_t(" \t\n\r")) const { return this->ltrim(ws).rtrim(ws); }
-
- pstring_t rpad(const pstring_t &ws, const size_type cnt) const;
-
- pstring_t ucase() const;
-
const string_type &cpp_string() const { return m_str; }
- static const size_type npos = static_cast<size_type>(-1);
-
-protected:
- string_type m_str;
+ static constexpr const size_type npos = static_cast<size_type>(-1);
private:
+ string_type m_str;
};
struct pu8_traits
{
- typedef char mem_t;
- typedef char code_t;
- typedef std::string string_type;
+ using mem_t = char;
+ using code_t = char;
+ using string_type = std::string;
static std::size_t len(const string_type &p) { return p.size(); }
- static std::size_t codelen(const mem_t *p) { return 1; }
- static std::size_t codelen(const code_t c) { return 1; }
+ static std::size_t codelen(const mem_t *p) { plib::unused_var(p); return 1; }
+ static std::size_t codelen(const code_t c) { plib::unused_var(c); return 1; }
static code_t code(const mem_t *p) { return *p; }
static void encode(const code_t c, string_type &s) { s += static_cast<mem_t>(c); }
static const mem_t *nthcode(const mem_t *p, const std::size_t n) { return &(p[n]); }
@@ -270,9 +226,9 @@ struct pu8_traits
/* No checking, this may deliver invalid codes */
struct putf8_traits
{
- typedef char mem_t;
- typedef char32_t code_t;
- typedef std::string string_type;
+ using mem_t = char;
+ using code_t = char32_t;
+ using string_type = std::string;
static std::size_t len(const string_type &p)
{
std::size_t ret = 0;
@@ -285,7 +241,7 @@ struct putf8_traits
}
static std::size_t codelen(const mem_t *p)
{
- const unsigned char *p1 = reinterpret_cast<const unsigned char *>(p);
+ const auto p1 = reinterpret_cast<const unsigned char *>(p);
if ((*p1 & 0x80) == 0x00)
return 1;
else if ((*p1 & 0xE0) == 0xC0)
@@ -312,7 +268,7 @@ struct putf8_traits
}
static code_t code(const mem_t *p)
{
- const unsigned char *p1 = reinterpret_cast<const unsigned char *>(p);
+ const auto p1 = reinterpret_cast<const unsigned char *>(p);
if ((*p1 & 0x80) == 0x00)
return *p1;
else if ((*p1 & 0xE0) == 0xC0)
@@ -361,9 +317,9 @@ struct putf8_traits
struct putf16_traits
{
- typedef char16_t mem_t;
- typedef char32_t code_t;
- typedef std::u16string string_type;
+ using mem_t = char16_t;
+ using code_t = char32_t;
+ using string_type = std::u16string;
static std::size_t len(const string_type &p)
{
std::size_t ret = 0;
@@ -371,7 +327,7 @@ struct putf16_traits
while (i != p.end())
{
// FIXME: check that size is equal
- uint16_t c = static_cast<uint16_t>(*i++);
+ auto c = static_cast<uint16_t>(*i++);
if (!((c & 0xd800) == 0xd800))
ret++;
}
@@ -379,7 +335,7 @@ struct putf16_traits
}
static std::size_t codelen(const mem_t *p)
{
- uint16_t c = static_cast<uint16_t>(*p);
+ auto c = static_cast<uint16_t>(*p);
return ((c & 0xd800) == 0xd800) ? 2 : 1;
}
static std::size_t codelen(const code_t c)
@@ -391,7 +347,7 @@ struct putf16_traits
}
static code_t code(const mem_t *p)
{
- uint32_t c = static_cast<uint32_t>(*p++);
+ auto c = static_cast<uint32_t>(*p++);
if ((c & 0xd800) == 0xd800)
{
c = (c - 0xd800) << 10;
@@ -401,7 +357,7 @@ struct putf16_traits
}
static void encode(code_t c, string_type &s)
{
- uint32_t cu = static_cast<uint32_t>(c);
+ auto cu = static_cast<uint32_t>(c);
if (c > 0xffff)
{ //make a surrogate pair
uint32_t t = ((cu - 0x10000) >> 10) + 0xd800;
@@ -425,9 +381,9 @@ struct putf16_traits
struct pwchar_traits
{
- typedef wchar_t mem_t;
- typedef char32_t code_t;
- typedef std::wstring string_type;
+ using mem_t = wchar_t;
+ using code_t = char32_t;
+ using string_type = std::wstring;
static std::size_t len(const string_type &p)
{
if (sizeof(wchar_t) == 2)
@@ -437,7 +393,7 @@ struct pwchar_traits
while (i != p.end())
{
// FIXME: check that size is equal
- uint32_t c = static_cast<uint32_t>(*i++);
+ auto c = static_cast<uint32_t>(*i++);
if (!((c & 0xd800) == 0xd800))
ret++;
}
@@ -451,7 +407,7 @@ struct pwchar_traits
{
if (sizeof(wchar_t) == 2)
{
- uint16_t c = static_cast<uint16_t>(*p);
+ auto c = static_cast<uint16_t>(*p);
return ((c & 0xd800) == 0xd800) ? 2 : 1;
}
else
@@ -470,7 +426,7 @@ struct pwchar_traits
{
if (sizeof(wchar_t) == 2)
{
- uint32_t c = static_cast<uint32_t>(*p++);
+ auto c = static_cast<uint32_t>(*p++);
if ((c & 0xd800) == 0xd800)
{
c = (c - 0xd800) << 10;
@@ -486,7 +442,7 @@ struct pwchar_traits
{
if (sizeof(wchar_t) == 2)
{
- uint32_t cu = static_cast<uint32_t>(c);
+ auto cu = static_cast<uint32_t>(c);
if (c > 0xffff)
{ //make a surrogate pair
uint32_t t = ((cu - 0x10000) >> 10) + 0xd800;
@@ -519,41 +475,280 @@ extern template struct pstring_t<putf8_traits>;
extern template struct pstring_t<putf16_traits>;
extern template struct pstring_t<pwchar_traits>;
-typedef pstring_t<putf8_traits> pstring;
-typedef pstring_t<putf16_traits> pu16string;
-typedef pstring_t<pwchar_traits> pwstring;
+#if (PSTRING_USE_STD_STRING)
+typedef std::string pstring;
+#else
+using pstring = pstring_t<putf8_traits>;
+#endif
+using putf8string = pstring_t<putf8_traits>;
+using pu16string = pstring_t<putf16_traits>;
+using pwstring = pstring_t<pwchar_traits>;
namespace plib
{
+ template<class T>
+ struct string_info
+ {
+ using mem_t = typename T::mem_t;
+ };
+
+ template<>
+ struct string_info<std::string>
+ {
+ using mem_t = char;
+ };
+
template<typename T>
pstring to_string(const T &v)
{
- return pstring(std::to_string(v), pstring::UTF8);
+ return pstring(std::to_string(v));
}
template<typename T>
pwstring to_wstring(const T &v)
{
- return pwstring(std::to_wstring(v), pwstring::UTF16);
+ return pwstring(std::to_wstring(v));
+ }
+
+ template <typename T, typename E = void>
+ struct pstonum_helper;
+
+ template<typename T>
+ struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value
+ && std::is_signed<T>::value>::type>
+ {
+ template <typename S>
+ long long operator()(const S &arg, std::size_t *idx)
+ {
+ return std::stoll(arg, idx);
+ }
+ };
+
+ template<typename T>
+ struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value
+ && !std::is_signed<T>::value>::type>
+ {
+ template <typename S>
+ unsigned long long operator()(const S &arg, std::size_t *idx)
+ {
+ return std::stoull(arg, idx);
+ }
+ };
+
+ template<typename T>
+ struct pstonum_helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
+ {
+ template <typename S>
+ long double operator()(const S &arg, std::size_t *idx)
+ {
+ return std::stold(arg, idx);
+ }
+ };
+
+ template<typename T, typename S>
+ T pstonum(const S &arg)
+ {
+ decltype(arg.c_str()) cstr = arg.c_str();
+ std::size_t idx(0);
+ auto ret = pstonum_helper<T>()(cstr, &idx);
+ using ret_type = decltype(ret);
+ if (ret >= static_cast<ret_type>(std::numeric_limits<T>::lowest())
+ && ret <= static_cast<ret_type>(std::numeric_limits<T>::max()))
+ //&& (ret == T(0) || std::abs(ret) >= std::numeric_limits<T>::min() ))
+ {
+ if (cstr[idx] != 0)
+ throw std::invalid_argument(std::string("Continuation after numeric value ends: ") + cstr);
+ }
+ else
+ {
+ throw std::out_of_range(std::string("Out of range: ") + cstr);
+ }
+ return static_cast<T>(ret);
+ }
+
+ template<typename R, typename T>
+ R pstonum_ne(const T &str, bool &err) noexcept
+ {
+ try
+ {
+ err = false;
+ return pstonum<R>(str);
+ }
+ catch (...)
+ {
+ err = true;
+ return R(0);
+ }
+ }
+
+ template<typename T>
+ typename T::size_type find_first_not_of(const T &str, const T &no)
+ {
+ typename T::size_type pos = 0;
+ for (auto it = str.begin(); it != str.end(); ++it, ++pos)
+ {
+ bool f = true;
+ for (typename T::value_type const jt : no)
+ {
+ if (*it == jt)
+ {
+ f = false;
+ break;
+ }
+ }
+ if (f)
+ return pos;
+ }
+ return T::npos;
+ }
+
+ template<typename T>
+ typename T::size_type find_last_not_of(const T &str, const T &no)
+ {
+ /* FIXME: reverse iterator */
+ typename T::size_type last_found = T::npos;
+ typename T::size_type pos = 0;
+ for (auto it = str.begin(); it != str.end(); ++it, ++pos)
+ {
+ bool f = true;
+ for (typename T::value_type const jt : no)
+ {
+ if (*it == jt)
+ {
+ f = false;
+ break;
+ }
+ }
+ if (f)
+ last_found = pos;
+ }
+ return last_found;
+ }
+
+ template<typename T>
+ T ltrim(const T &str, const T &ws = T(" \t\n\r"))
+ {
+ auto f = find_first_not_of(str, ws);
+ return (f == T::npos) ? T() : str.substr(f);
}
-}
+
+ template<typename T>
+ T rtrim(const T &str, const T &ws = T(" \t\n\r"))
+ {
+ auto f = find_last_not_of(str, ws);
+ return (f == T::npos) ? T() : str.substr(0, f + 1);
+ }
+
+ template<typename T>
+ T trim(const T &str, const T &ws = T(" \t\n\r"))
+ {
+ return rtrim(ltrim(str, ws), ws);
+ }
+
+ template<typename T>
+ T left(const T &str, typename T::size_type len)
+ {
+ return str.substr(0, len);
+ }
+
+ template<typename T>
+ T right(const T &str, typename T::size_type nlen)
+ {
+ return nlen >= str.length() ? str : str.substr(str.length() - nlen, nlen);
+ }
+
+ template<typename T>
+ bool startsWith(const T &str, const T &arg)
+ {
+ return (arg == left(str, arg.length()));
+ }
+
+ template<typename T>
+ bool endsWith(const T &str, const T &arg)
+ {
+ return (right(str, arg.length()) == arg);
+ }
+
+ template<typename T>
+ bool startsWith(const T &str, const char *arg)
+ {
+ return (left(str, std::strlen(arg)) == arg);
+ }
+
+ template<typename T>
+ bool endsWith(const T &str, const char *arg)
+ {
+ return (right(str, std::strlen(arg)) == arg);
+ }
+
+ template<typename T>
+ T ucase(const T &str)
+ {
+ T ret;
+ for (const auto &c : str)
+ if (c >= 'a' && c <= 'z')
+ ret += (c - 'a' + 'A');
+ else
+ ret += c;
+ return ret;
+ }
+
+ template<typename T>
+ T rpad(const T &str, const T &ws, const typename T::size_type cnt)
+ {
+ // FIXME: pstringbuffer ret(*this);
+
+ T ret(str);
+ typename T::size_type wsl = ws.length();
+ for (auto i = ret.length(); i < cnt; i+=wsl)
+ ret += ws;
+ return ret;
+ }
+
+ template<typename T>
+ T replace_all(const T &str, const T &search, const T &replace)
+ {
+ T ret;
+ const typename T::size_type slen = search.length();
+
+ typename T::size_type last_s = 0;
+ typename T::size_type s = str.find(search, last_s);
+ while (s != T::npos)
+ {
+ ret += str.substr(last_s, s - last_s);
+ ret += replace;
+ last_s = s + slen;
+ s = str.find(search, last_s);
+ }
+ ret += str.substr(last_s);
+ return ret;
+ }
+
+ template<typename T, typename T1, typename T2>
+ T replace_all(const T &str, const T1 &search, const T2 &replace)
+ {
+ return replace_all(str, static_cast<T>(search), static_cast<T>(replace));
+ }
+
+} // namespace plib
// custom specialization of std::hash can be injected in namespace std
namespace std
{
+
template<typename T> struct hash<pstring_t<T>>
{
- typedef pstring_t<T> argument_type;
- typedef std::size_t result_type;
+ using argument_type = pstring_t<T>;
+ using result_type = std::size_t;
result_type operator()(argument_type const& s) const
{
- const pstring::mem_t *string = s.c_str();
+ const typename argument_type::mem_t *string = s.c_str();
result_type result = 5381;
- for (pstring::mem_t c = *string; c != 0; c = *string++)
+ for (typename argument_type::mem_t c = *string; c != 0; c = *string++)
result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ static_cast<result_type>(c);
return result;
}
};
-}
+} // namespace std
#endif /* PSTRING_H_ */
diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h
new file mode 100644
index 00000000000..32ccc4f7b0d
--- /dev/null
+++ b/src/lib/netlist/plib/ptime.h
@@ -0,0 +1,136 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * ptime.h
+ */
+
+#ifndef PTIME_H_
+#define PTIME_H_
+
+#include "pconfig.h"
+#include "ptypes.h"
+
+#include <cstdint>
+
+// ----------------------------------------------------------------------------------------
+// netlist_time
+// ----------------------------------------------------------------------------------------
+
+namespace plib
+{
+
+ template <typename TYPE, TYPE RES>
+ struct ptime final
+ {
+ public:
+
+ using internal_type = TYPE;
+ using mult_type = TYPE;
+
+ constexpr ptime() noexcept : m_time(0) {}
+
+ ~ptime() noexcept = default;
+
+ constexpr ptime(const ptime &rhs) noexcept = default;
+ constexpr ptime(ptime &&rhs) noexcept = default;
+ constexpr explicit ptime(const internal_type &time) noexcept : m_time(time) {}
+ constexpr explicit ptime(internal_type &&time) noexcept : m_time(time) {}
+ C14CONSTEXPR ptime &operator=(const ptime &rhs) noexcept = default;
+ C14CONSTEXPR ptime &operator=(ptime &&rhs) noexcept = default;
+
+ constexpr explicit ptime(const double t) = delete;
+ //: m_time((internal_type) ( t * (double) resolution)) { }
+ constexpr explicit ptime(const internal_type nom, const internal_type den) noexcept
+ : m_time(nom * (RES / den)) { }
+
+ C14CONSTEXPR ptime &operator+=(const ptime rhs) noexcept { m_time += rhs.m_time; return *this; }
+ C14CONSTEXPR ptime &operator-=(const ptime rhs) noexcept { m_time -= rhs.m_time; return *this; }
+ C14CONSTEXPR ptime &operator*=(const mult_type factor) noexcept { m_time *= static_cast<internal_type>(factor); return *this; }
+
+ friend constexpr const ptime operator-(ptime lhs, const ptime rhs) noexcept
+ {
+ return ptime(lhs.m_time - rhs.m_time);
+ }
+
+ friend constexpr const ptime operator+(ptime lhs, const ptime rhs) noexcept
+ {
+ return ptime(lhs.m_time + rhs.m_time);
+ }
+
+ friend constexpr const ptime operator*(ptime lhs, const mult_type &factor) noexcept
+ {
+ return ptime(lhs.m_time * factor);
+ }
+
+ friend constexpr mult_type operator/(const ptime lhs, const ptime rhs) noexcept
+ {
+ return static_cast<mult_type>(lhs.m_time / rhs.m_time);
+ }
+
+ friend constexpr bool operator<(const ptime lhs, const ptime rhs) noexcept
+ {
+ return (lhs.m_time < rhs.m_time);
+ }
+
+ friend constexpr bool operator>(const ptime lhs, const ptime rhs) noexcept
+ {
+ return (rhs < lhs);
+ }
+
+ friend constexpr bool operator<=(const ptime lhs, const ptime rhs) noexcept
+ {
+ return !(lhs > rhs);
+ }
+
+ friend constexpr bool operator>=(const ptime lhs, const ptime rhs) noexcept
+ {
+ return !(lhs < rhs);
+ }
+
+ friend constexpr bool operator==(const ptime lhs, const ptime rhs) noexcept
+ {
+ return lhs.m_time == rhs.m_time;
+ }
+
+ friend constexpr bool operator!=(const ptime lhs, const ptime rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+
+ constexpr internal_type as_raw() const noexcept { return m_time; }
+ constexpr double as_double() const noexcept
+ {
+ return static_cast<double>(m_time) * inv_res;
+ }
+
+ // for save states ....
+ C14CONSTEXPR internal_type *get_internaltype_ptr() noexcept { return &m_time; }
+
+ static constexpr ptime from_nsec(const internal_type ns) noexcept { return ptime(ns, UINT64_C(1000000000)); }
+ static constexpr ptime from_usec(const internal_type us) noexcept { return ptime(us, UINT64_C( 1000000)); }
+ static constexpr ptime from_msec(const internal_type ms) noexcept { return ptime(ms, UINT64_C( 1000)); }
+ static constexpr ptime from_sec(const internal_type s) noexcept { return ptime(s, UINT64_C( 1)); }
+ static constexpr ptime from_hz(const internal_type hz) noexcept { return ptime(1 , hz); }
+ static constexpr ptime from_raw(const internal_type raw) noexcept { return ptime(raw); }
+ static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast<internal_type>( t * static_cast<double>(RES)), RES); }
+
+ static constexpr ptime zero() noexcept { return ptime(0, RES); }
+ static constexpr ptime quantum() noexcept { return ptime(1, RES); }
+ static constexpr ptime never() noexcept { return ptime(plib::numeric_limits<internal_type>::max(), RES); }
+ static constexpr internal_type resolution() noexcept { return RES; }
+
+ constexpr internal_type in_nsec() const noexcept { return m_time / (RES / UINT64_C(1000000000)); }
+ constexpr internal_type in_usec() const noexcept { return m_time / (RES / UINT64_C( 1000000)); }
+ constexpr internal_type in_msec() const noexcept { return m_time / (RES / UINT64_C( 1000)); }
+ constexpr internal_type in_sec() const noexcept { return m_time / (RES / UINT64_C( 1)); }
+
+ private:
+ static constexpr const double inv_res = 1.0 / static_cast<double>(RES);
+ internal_type m_time;
+ };
+
+
+} // namespace plib
+
+
+#endif /* PTIME_H_ */
diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h
index 0934a86fdf2..bda62099150 100644
--- a/src/lib/netlist/plib/ptypes.h
+++ b/src/lib/netlist/plib/ptypes.h
@@ -9,10 +9,20 @@
#define PTYPES_H_
#include "pconfig.h"
-#include "pstring.h"
-#include <type_traits>
#include <limits>
+#include <string>
+#include <type_traits>
+
+#define COPYASSIGNMOVE(name, def) \
+ name(const name &) = def; \
+ name(name &&) noexcept = def; \
+ name &operator=(const name &) = def; \
+ name &operator=(name &&) noexcept = def;
+
+#define COPYASSIGN(name, def) \
+ name(const name &) = def; \
+ name &operator=(const name &) = def; \
namespace plib
{
@@ -25,14 +35,14 @@ namespace plib
template<> struct is_integral<INT128> { static constexpr bool value = true; };
template<> struct numeric_limits<UINT128>
{
- static inline constexpr UINT128 max()
+ static constexpr UINT128 max()
{
return ~((UINT128)0);
}
};
template<> struct numeric_limits<INT128>
{
- static inline constexpr INT128 max()
+ static constexpr INT128 max()
{
return (~((UINT128)0)) >> 1;
}
@@ -45,56 +55,98 @@ namespace plib
struct nocopyassignmove
{
- protected:
- nocopyassignmove() = default;
- ~nocopyassignmove() = default;
- private:
nocopyassignmove(const nocopyassignmove &) = delete;
nocopyassignmove(nocopyassignmove &&) = delete;
nocopyassignmove &operator=(const nocopyassignmove &) = delete;
nocopyassignmove &operator=(nocopyassignmove &&) = delete;
+ protected:
+ nocopyassignmove() = default;
+ ~nocopyassignmove() = default;
};
struct nocopyassign
{
+ nocopyassign(const nocopyassign &) = delete;
+ nocopyassign &operator=(const nocopyassign &) = delete;
protected:
nocopyassign() = default;
~nocopyassign() = default;
- private:
- nocopyassign(const nocopyassign &) = delete;
- nocopyassign &operator=(const nocopyassign &) = delete;
+ nocopyassign(nocopyassign &&) = default;
+ nocopyassign &operator=(nocopyassign &&) = default;
};
//============================================================
- // penum - strongly typed enumeration
+ // Avoid unused variable warnings
//============================================================
+ template<typename... Ts>
+ inline void unused_var(Ts&&...) {}
- struct penum_base
+ //============================================================
+ // is_pow2
+ //============================================================
+ template <typename T>
+ constexpr bool is_pow2(T v) noexcept
{
- protected:
- static int from_string_int(const char *str, const char *x);
- static pstring nthstr(int n, const char *str);
- };
+ static_assert(is_integral<T>::value, "is_pow2 needs integer arguments");
+ return !(v & (v-1));
+ }
+
+
+ //============================================================
+ // abs, lcd, gcm
+ //============================================================
+
+ template<typename T>
+ constexpr
+ typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type
+ abs(T v)
+ {
+ return v < 0 ? -v : v;
+ }
+
+ template<typename T>
+ constexpr
+ typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type
+ abs(T v)
+ {
+ return v;
+ }
+
+ template<typename M, typename N>
+ constexpr typename std::common_type<M, N>::type
+ gcd(M m, N n)
+ {
+ static_assert(std::is_integral<M>::value, "gcd: M must be an integer");
+ static_assert(std::is_integral<N>::value, "gcd: N must be an integer");
+
+ return m == 0 ? plib::abs(n)
+ : n == 0 ? plib::abs(m)
+ : gcd(n, m % n);
+ }
+
+ template<typename M, typename N>
+ constexpr typename std::common_type<M, N>::type
+ lcm(M m, N n)
+ {
+ static_assert(std::is_integral<M>::value, "lcm: M must be an integer");
+ static_assert(std::is_integral<N>::value, "lcm: N must be an integer");
+
+ return (m != 0 && n != 0) ? (plib::abs(m) / gcd(m, n)) * plib::abs(n) : 0;
+ }
+
+} // namespace plib
-}
-
-#define P_ENUM(ename, ...) \
- struct ename : public plib::penum_base { \
- enum E { __VA_ARGS__ }; \
- ename (E v) : m_v(v) { } \
- bool set_from_string (const pstring &s) { \
- static char const *const strings = # __VA_ARGS__; \
- int f = from_string_int(strings, s.c_str()); \
- if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
- } \
- operator E() const {return m_v;} \
- bool operator==(const ename &rhs) const {return m_v == rhs.m_v;} \
- bool operator==(const E &rhs) const {return m_v == rhs;} \
- const pstring name() const { \
- static char const *const strings = # __VA_ARGS__; \
- return nthstr(static_cast<int>(m_v), strings); \
- } \
- private: E m_v; };
+//============================================================
+// Define a "has member" trait.
+//============================================================
+#define PDEFINE_HAS_MEMBER(name, member) \
+ template <typename T> class name \
+ { \
+ template <typename U> static long test(decltype(&U:: member)); \
+ template <typename U> static char test(...); \
+ public: \
+ static constexpr const bool value = sizeof(test<T>(nullptr)) == sizeof(long); \
+ }
#endif /* PTYPES_H_ */
diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp
index c34102417ec..b62cbf60865 100644
--- a/src/lib/netlist/plib/putil.cpp
+++ b/src/lib/netlist/plib/putil.cpp
@@ -2,13 +2,13 @@
// copyright-holders:Couriersud
#include "putil.h"
-#include "ptypes.h"
#include "plists.h"
+#include "ptypes.h"
-#include <cstdlib>
#include <algorithm>
-#include <initializer_list>
+#include <cstdlib>
#include <cstring>
+#include <initializer_list>
namespace plib
{
@@ -17,7 +17,7 @@ namespace plib
const pstring buildpath(std::initializer_list<pstring> list )
{
pstring ret = "";
- for( auto elem : list )
+ for( const auto &elem : list )
{
if (ret == "")
ret = elem;
@@ -33,12 +33,12 @@ namespace plib
const pstring environment(const pstring &var, const pstring &default_val)
{
- if (getenv(var.c_str()) == nullptr)
+ if (std::getenv(var.c_str()) == nullptr)
return default_val;
else
- return pstring(getenv(var.c_str()), pstring::UTF8);
+ return pstring(std::getenv(var.c_str()));
}
- }
+ } // namespace util
std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty)
{
@@ -64,6 +64,36 @@ namespace plib
return ret;
}
+ std::vector<std::string> psplit_r(const std::string &stri,
+ const std::string &token,
+ const std::size_t maxsplit)
+ {
+ std::string str(stri);
+ std::vector<std::string> result;
+ std::size_t splits = 0;
+
+ while(str.size())
+ {
+ std::size_t index = str.rfind(token);
+ bool found = index!=std::string::npos;
+ if (found)
+ splits++;
+ if ((splits <= maxsplit || maxsplit == 0) && found)
+ {
+ result.push_back(str.substr(index+token.size()));
+ str = str.substr(0, index);
+ if (str.size()==0)
+ result.push_back(str);
+ }
+ else
+ {
+ result.push_back(str);
+ str = "";
+ }
+ }
+ return result;
+ }
+
std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl)
{
pstring col = "";
@@ -72,7 +102,7 @@ namespace plib
auto i = str.begin();
while (i != str.end())
{
- std::size_t p = static_cast<std::size_t>(-1);
+ auto p = static_cast<std::size_t>(-1);
for (std::size_t j=0; j < onstrl.size(); j++)
{
if (std::equal(onstrl[j].begin(), onstrl[j].end(), i))
@@ -92,7 +122,7 @@ namespace plib
}
else
{
- pstring::code_t c = *i;
+ pstring::value_type c = *i;
col += c;
i++;
}
@@ -131,31 +161,8 @@ namespace plib
return cnt;
return -1;
}
- pstring penum_base::nthstr(int n, const char *str)
+ std::string penum_base::nthstr(int n, const char *str)
{
- char buf[64];
- char *bufp = buf;
- int cur = 0;
- while (*str)
- {
- if (cur == n)
- {
- if (*str == ',')
- {
- *bufp = 0;
- return pstring(buf, pstring::UTF8);
- }
- else if (*str != ' ')
- *bufp++ = *str;
- }
- else
- {
- if (*str == ',')
- cur++;
- }
- str++;
- }
- *bufp = 0;
- return pstring(buf, pstring::UTF8);
+ return psplit(str, ",", false)[static_cast<std::size_t>(n)];
}
} // namespace plib
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index 8d59c0357e2..e8145361d9d 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -5,27 +5,32 @@
*
*/
-#ifndef P_UTIL_H_
-#define P_UTIL_H_
+#ifndef PUTIL_H_
+#define PUTIL_H_
#include "pstring.h"
-#include <initializer_list>
#include <algorithm>
-#include <vector> // <<= needed by windows build
+#include <initializer_list>
+#include <vector>
+
+#define PSTRINGIFY_HELP(y) # y
+#define PSTRINGIFY(x) PSTRINGIFY_HELP(x)
+
namespace plib
{
+
namespace util
{
const pstring buildpath(std::initializer_list<pstring> list );
const pstring environment(const pstring &var, const pstring &default_val);
- }
+ } // namespace util
namespace container
{
- template <class C>
- bool contains(C &con, const typename C::value_type &elem)
+ template <class C, class T>
+ bool contains(C &con, const T &elem)
{
return std::find(con.begin(), con.end(), elem) != con.end();
}
@@ -51,7 +56,51 @@ namespace plib
{
con.erase(std::remove(con.begin(), con.end(), elem), con.end());
}
- }
+ } // namespace container
+
+ /* May be further specialized .... This is the generic version */
+ template <typename T>
+ struct constants
+ {
+ static constexpr T zero() noexcept { return static_cast<T>(0); }
+ static constexpr T one() noexcept { return static_cast<T>(1); }
+ static constexpr T two() noexcept { return static_cast<T>(2); }
+
+ /*!
+ * \brief Electric constant of vacuum
+ */
+ static constexpr T eps_0() noexcept { return static_cast<T>(8.854187817e-12); }
+ /*!
+ * \brief Relative permittivity of Silicon dioxide
+ */
+ static constexpr T eps_SiO2() noexcept { return static_cast<T>(3.9); }
+ /*!
+ * \brief Relative permittivity of Silicon
+ */
+ static constexpr T eps_Si() noexcept { return static_cast<T>(11.7); }
+ /*!
+ * \brief Boltzmann constant
+ */
+ static constexpr T k_b() noexcept { return static_cast<T>(1.38064852e-23); }
+ /*!
+ * \brief room temperature (gives VT = 0.02585 at T=300)
+ */
+ static constexpr T T0() noexcept { return static_cast<T>(300); }
+ /*!
+ * \brief Elementary charge
+ */
+ static constexpr T Q_e() noexcept { return static_cast<T>(1.6021765314e-19); }
+ /*!
+ * \brief Intrinsic carrier concentration in 1/m^3 of Silicon
+ */
+ static constexpr T NiSi() noexcept { return static_cast<T>(1.45e16); }
+
+ template <typename V>
+ static constexpr const T cast(V &&v) noexcept { return static_cast<T>(v); }
+ };
+
+ static_assert(noexcept(constants<double>::one()) == true, "Not evaluated as constexpr");
+
template <class C>
struct indexed_compare
@@ -69,7 +118,41 @@ namespace plib
std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty = false);
std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl);
+ std::vector<std::string> psplit_r(const std::string &stri,
+ const std::string &token,
+ const std::size_t maxsplit);
+
+
+ //============================================================
+ // penum - strongly typed enumeration
+ //============================================================
+
+ struct penum_base
+ {
+ protected:
+ static int from_string_int(const char *str, const char *x);
+ static std::string nthstr(int n, const char *str);
+ };
+
+} // namespace plib
+
+#define P_ENUM(ename, ...) \
+ struct ename : public plib::penum_base { \
+ enum E { __VA_ARGS__ }; \
+ ename (E v) : m_v(v) { } \
+ bool set_from_string (const std::string &s) { \
+ static char const *const strings = # __VA_ARGS__; \
+ int f = from_string_int(strings, s.c_str()); \
+ if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
+ } \
+ operator E() const {return m_v;} \
+ bool operator==(const ename &rhs) const {return m_v == rhs.m_v;} \
+ bool operator==(const E &rhs) const {return m_v == rhs;} \
+ std::string name() const { \
+ static char const *const strings = # __VA_ARGS__; \
+ return nthstr(static_cast<int>(m_v), strings); \
+ } \
+ private: E m_v; };
-}
-#endif /* P_UTIL_H_ */
+#endif /* PUTIL_H_ */
diff --git a/src/lib/netlist/plib/vector_ops.h b/src/lib/netlist/plib/vector_ops.h
new file mode 100644
index 00000000000..8043c48f61c
--- /dev/null
+++ b/src/lib/netlist/plib/vector_ops.h
@@ -0,0 +1,151 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * vector_ops.h
+ *
+ * Base vector operations
+ *
+ */
+
+#ifndef PLIB_VECTOR_OPS_H_
+#define PLIB_VECTOR_OPS_H_
+
+#include "pconfig.h"
+
+#include <algorithm>
+#include <cmath>
+#include <type_traits>
+
+#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+#if !(__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 3))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+#endif
+
+namespace plib
+{
+ template<typename VT, typename T>
+ void vec_set_scalar(const std::size_t n, VT &v, T && scalar)
+ {
+ const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
+ for ( std::size_t i = 0; i < n; i++ )
+ v[i] = s;
+ }
+
+ template<typename VT, typename VS>
+ void vec_set(const std::size_t n, VT &v, const VS & source)
+ {
+ for ( std::size_t i = 0; i < n; i++ )
+ v[i] = source[i];
+ }
+
+ template<typename T, typename V1, typename V2>
+ T vec_mult(const std::size_t n, const V1 & v1, const V2 & v2 )
+ {
+ using b8 = T[8];
+ PALIGNAS_VECTOROPT() b8 value = {0};
+ for (std::size_t i = 0; i < n ; i++ )
+ {
+ value[i & 7] += v1[i] * v2[i];
+ }
+ return value[0] + value[1] + value[2] + value[3] + value[4] + value[5] + value[6] + value[7];
+ }
+
+ template<typename T, typename VT>
+ T vec_mult2(const std::size_t n, const VT &v)
+ {
+ using b8 = T[8];
+ PALIGNAS_VECTOROPT() b8 value = {0};
+ for (std::size_t i = 0; i < n ; i++ )
+ {
+ value[i & 7] += v[i] * v[i];
+ }
+ return value[0] + value[1] + value[2] + value[3] + value[4] + value[5] + value[6] + value[7];
+ }
+
+ template<typename T, typename VT>
+ T vec_sum(const std::size_t n, const VT &v)
+ {
+ if (n<8)
+ {
+ T value(0);
+ for (std::size_t i = 0; i < n ; i++ )
+ value += v[i];
+
+ return value;
+ }
+ else
+ {
+ using b8 = T[8];
+ PALIGNAS_VECTOROPT() b8 value = {0};
+ for (std::size_t i = 0; i < n ; i++ )
+ value[i & 7] += v[i];
+
+ return ((value[0] + value[1]) + (value[2] + value[3])) + ((value[4] + value[5]) + (value[6] + value[7]));
+ }
+ }
+
+ template<typename VV, typename T, typename VR>
+ void vec_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar)
+ {
+ const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] = s * v[i];
+ }
+
+ template<typename VR, typename VV, typename T>
+ void vec_add_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar)
+ {
+ const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] += s * v[i];
+ }
+
+ template<typename T>
+ void vec_add_mult_scalar_p(const std::size_t n, T * result, const T * v, T scalar)
+ {
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] += scalar * v[i];
+ }
+
+ template<typename R, typename V>
+ void vec_add_ip(const std::size_t n, R & result, const V & v)
+ {
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] += v[i];
+ }
+
+ template<typename VR, typename V1, typename V2>
+ void vec_sub(const std::size_t n, VR & result, const V1 &v1, const V2 & v2)
+ {
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] = v1[i] - v2[i];
+ }
+
+ template<typename V, typename T>
+ void vec_scale(const std::size_t n, V & v, T &&scalar)
+ {
+ const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
+ for ( std::size_t i = 0; i < n; i++ )
+ v[i] *= s;
+ }
+
+ template<typename T, typename V>
+ T vec_maxabs(const std::size_t n, const V & v)
+ {
+ T ret = 0.0;
+ for ( std::size_t i = 0; i < n; i++ )
+ ret = std::max(ret, std::abs(v[i]));
+
+ return ret;
+ }
+} // namespace plib
+
+#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+#if !(__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 3))
+#pragma GCC diagnostic pop
+#endif
+#endif
+
+#endif /* PLIB_VECTOR_OPS_H_ */