diff options
author | 2019-03-25 23:13:40 +0100 | |
---|---|---|
committer | 2019-03-25 23:13:40 +0100 | |
commit | b380514764cf857469bae61c11143a19f79a74c5 (patch) | |
tree | 63c8012e262618f08a332da31dd714281aa2c5ed /src/lib/netlist/plib | |
parent | c24473ddff715ecec2e258a6eb38960cf8c8e98e (diff) |
Revert "conflict resolution (nw)"
This reverts commit c24473ddff715ecec2e258a6eb38960cf8c8e98e, reversing
changes made to 009cba4fb8102102168ef32870892438327f3705.
Diffstat (limited to 'src/lib/netlist/plib')
38 files changed, 1497 insertions, 4004 deletions
diff --git a/src/lib/netlist/plib/gmres.h b/src/lib/netlist/plib/gmres.h deleted file mode 100644 index 2c357e97624..00000000000 --- a/src/lib/netlist/plib/gmres.h +++ /dev/null @@ -1,450 +0,0 @@ -// 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 deleted file mode 100644 index 4cc027f0d8f..00000000000 --- a/src/lib/netlist/plib/mat_cr.h +++ /dev/null @@ -1,530 +0,0 @@ -// 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 new file mode 100644 index 00000000000..e4d31985b23 --- /dev/null +++ b/src/lib/netlist/plib/palloc.cpp @@ -0,0 +1,105 @@ +// 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 15fede3a99b..a35bc50ff17 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -8,427 +8,172 @@ #ifndef PALLOC_H_ #define PALLOC_H_ -#include "pconfig.h" #include "pstring.h" -#include "ptypes.h" -#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 +#include <memory> namespace plib { - //============================================================ - // 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 +//============================================================ +// 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) { - 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); + 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; } - //============================================================ - // Memory allocation - //============================================================ - - struct aligned_arena + owned_ptr(owned_ptr &&r) noexcept { - 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 + m_is_owned = r.m_is_owned; + m_ptr = r.m_ptr; + r.m_is_owned = false; + r.m_ptr = nullptr; } - template <typename T, std::size_t ALIGN> - constexpr const T *assume_aligned_ptr(const T *p) noexcept + template<typename DC> + owned_ptr(owned_ptr<DC> &&r) 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"); -#if (USE_ALIGNED_HINTS) - return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN)); -#else - return p; -#endif + m_ptr = static_cast<SC *>(r.get()); + m_is_owned = r.is_owned(); + r.release(); } - // FIXME: remove - template<typename T, typename... Args> - inline T *pnew(Args&&... args) + ~owned_ptr() { - auto *p = aligned_arena::allocate(alignof(T), sizeof(T)); - return new(p) T(std::forward<Args>(args)...); + if (m_is_owned && (m_ptr != nullptr)) + delete m_ptr; + m_is_owned = false; + m_ptr = nullptr; } - - template<typename T> - inline void pdelete(T *ptr) + template<typename DC, typename... Args> + static owned_ptr Create(Args&&... args) { - ptr->~T(); - aligned_arena::deallocate(ptr); + owned_ptr a; + DC *x = new DC(std::forward<Args>(args)...); + a.m_ptr = static_cast<SC *>(x); + return std::move(a); } - - 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) + template<typename... Args> + static owned_ptr Create(Args&&... args) { - return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...)); + owned_ptr a; + a.m_ptr = new SC(std::forward<Args>(args)...); + return std::move(a); } - -#if 0 - template<typename T, typename... Args> - static owned_ptr<T> make_owned(Args&&... args) + SC * release() { - return owned_ptr<T>(pnew<T>(std::forward<Args>(args)...), true); + SC *tmp = m_ptr; + m_is_owned = false; + m_ptr = nullptr; + return tmp; } -#endif - - - template <class T, std::size_t ALIGN = alignof(T)> - using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>; - - //============================================================ - // traits to determine alignment size and stride size - // from types supporting alignment - //============================================================ - PDEFINE_HAS_MEMBER(has_align, align_size); + bool is_owned() const { return m_is_owned; } - template <typename T, typename X = void> - struct align_traits - { - 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; - }; + 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; +}; - template <typename T> - struct align_traits<T, typename std::enable_if<has_align<T>::value, void>::type> +class mempool +{ +private: + struct 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; + 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; }; - //============================================================ - // Aligned vector - //============================================================ + size_t new_block(); + size_t mininfosize(); - // 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>> + struct info { - public: - using base = std::vector<T, aligned_allocator<T, ALIGN>>; + info() : m_block(0) { } + size_t m_block; + }; - 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; + size_t m_min_alloc; + size_t m_min_align; - using base::base; + std::vector<block> m_blocks; - 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]; - } +public: + mempool(size_t min_alloc, size_t min_align); + ~mempool(); - pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); } - const_pointer data() const noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); } + void *alloc(size_t size); + void free(void *ptr); - }; +}; -} // namespace plib +} #endif /* PALLOC_H_ */ diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h deleted file mode 100644 index 1be37b908cd..00000000000 --- a/src/lib/netlist/plib/parray.h +++ /dev/null @@ -1,126 +0,0 @@ -// 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 953d948e062..971d19b3645 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 8ce0eca23b3..a229128e7b8 100644 --- a/src/lib/netlist/plib/pchrono.h +++ b/src/lib/netlist/plib/pchrono.h @@ -9,17 +9,16 @@ #define PCHRONO_H_ #include "pconfig.h" -#include "ptypes.h" -#include <chrono> #include <cstdint> +#include <chrono> namespace plib { namespace chrono { template <typename T> struct sys_ticks { - using type = typename T::rep; + typedef typename T::rep type; 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; } @@ -146,7 +145,7 @@ namespace chrono { struct counter { counter() : m_count(0) { } - using type = uint_least64_t; + typedef uint_least64_t type; type operator()() const { return m_count; } void inc() { ++m_count; } void reset() { m_count = 0; } @@ -158,7 +157,7 @@ namespace chrono { template<> struct counter<false> { - using type = uint_least64_t; + typedef uint_least64_t type; constexpr type operator()() const { return 0; } void inc() const { } void reset() const { } @@ -169,28 +168,15 @@ namespace chrono { template< typename T, bool enabled_ = true> struct timer { - 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; + typedef typename T::type type; + typedef uint_least64_t ctype; 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; } @@ -199,7 +185,7 @@ namespace chrono { double as_seconds() const { return static_cast<double>(total()) / static_cast<double>(T::per_second()); } - guard_t guard() { return guard_t(*this); } + constexpr static bool enabled = enabled_; private: type m_time; ctype m_count; @@ -208,31 +194,19 @@ namespace chrono { template<typename T> struct timer<T, false> { - 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() { } - }; - + typedef typename T::type type; + typedef uint_least64_t ctype; 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 d66b342f815..0200c305ecd 100644 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -21,46 +21,18 @@ * if PHAS_RDTSCP == 1 */ #ifndef PUSE_ACCURATE_STATS -#define PUSE_ACCURATE_STATS (0) +#define PUSE_ACCURATE_STATS (1) #endif /* * Set this to one if you want to use 128 bit int for ptime. - * This is about 5% slower on a kaby lake processor. + * This is for tests only. */ #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 * @@ -75,13 +47,6 @@ * *============================================================*/ -#ifndef NVCCBUILD -#define NVCCBUILD (0) -#endif - -#if NVCCBUILD -#define C14CONSTEXPR -#else #if __cplusplus == 201103L #define C14CONSTEXPR #elif __cplusplus == 201402L @@ -93,7 +58,6 @@ #else #error "C++ version not supported" #endif -#endif #ifndef PHAS_INT128 #define PHAS_INT128 (0) @@ -104,6 +68,17 @@ 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 0d32bead51d..13827eaf24c 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 = new CHAR[char_count]; + result = palloc_array<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 = new WCHAR[char_count]; + result = palloc_array<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()); - delete [] buffer; + pfree_array(buffer); #elif defined(EMSCRIPTEN) //no-op #else @@ -88,11 +88,9 @@ 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()); @@ -106,7 +104,7 @@ dynlib::dynlib(const pstring &path, const pstring &libname) { //printf("win: library <%s> not found!\n", libname.c_str()); } - delete [] buffer; + pfree_array(buffer); #elif defined(EMSCRIPTEN) //no-op #else @@ -141,7 +139,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()); @@ -150,4 +148,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 1454c053298..7c9412593c9 100644 --- a/src/lib/netlist/plib/pdynlib.h +++ b/src/lib/netlist/plib/pdynlib.h @@ -8,31 +8,28 @@ #define PDYNLIB_H_ #include "pstring.h" -#include "ptypes.h" namespace plib { // ---------------------------------------------------------------------------------------- // pdynlib: dynamic loading of libraries ... // ---------------------------------------------------------------------------------------- -class dynlib : public nocopyassignmove +class dynlib { 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; @@ -67,6 +64,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 8d6907d66f2..a4ed8f367e0 100644 --- a/src/lib/netlist/plib/pexception.cpp +++ b/src/lib/netlist/plib/pexception.cpp @@ -9,7 +9,6 @@ #include "pfmtlog.h" #include <cfenv> -#include <iostream> #if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__) #define HAS_FEENABLE_EXCEPT (1) @@ -18,113 +17,127 @@ #endif namespace plib { - - //============================================================ - // terminate - //============================================================ - - void terminate(const pstring &msg) noexcept - { - std::cerr << msg.c_str() << "\n"; - std::terminate(); - } - - - //============================================================ - // 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) - { - } - - - file_write_e::file_write_e(const pstring &filename) - : file_e("File write failed: {}", filename) +//============================================================ +// 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) { + 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 +} - 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() +fpsignalenabler::~fpsignalenabler() +{ +#if HAS_FEENABLE_EXCEPT + if (m_enable) { - #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 + 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::supported() +{ + return true; +} - bool fpsignalenabler::global_enable(bool enable) - { - bool old = m_enable; - m_enable = enable; - return old; - } +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 28a3ac1adf1..4827081b754 100644 --- a/src/lib/netlist/plib/pexception.h +++ b/src/lib/netlist/plib/pexception.h @@ -9,116 +9,118 @@ #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 af87251fbdf..b8b5fcb3b91 100644 --- a/src/lib/netlist/plib/pfmtlog.cpp +++ b/src/lib/netlist/plib/pfmtlog.cpp @@ -8,96 +8,83 @@ #include "pfmtlog.h" #include "palloc.h" -#include <algorithm> -#include <array> -#include <cstdarg> -#include <cstdio> -#include <cstdlib> #include <cstring> -#include <iostream> +#include <cstdlib> +#include <cstdarg> +#include <algorithm> #include <locale> +#include <iostream> namespace plib { pfmt &pfmt::format_element(const char *l, const unsigned cfmt_spec, ...) { va_list ap; - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - std::array<char, 2048> buf; + va_start(ap, cfmt_spec); + pstring fmt("%"); + char buf[2048]; // FIXME std::size_t sl; - bool found_abs = false; m_arg++; - 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(); + pstring search("{"); + search += plib::to_string(m_arg); + sl = search.length(); - auto p = m_str.find(search + ":"); - sl++; // ":" - if (p == pstring::npos) // no further specifiers + 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 { - p = m_str.find(search + "}"); - if (p == pstring::npos) // not found try default - { - 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) - { - auto p1 = m_str.find("}", p); - if (p1 != pstring::npos) - { - sl = p1 - p + 1; - fmt += m_str.substr(p+1, p1 - p - 1); - } - } - } + sl = 2; + p = m_str.find("{}"); } - else + if (p == pstring::npos) { - // found absolute positional place holder - auto p1 = m_str.find("}", p); - if (p1 != pstring::npos) + sl=1; + p = m_str.find("{"); + if (p != 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; + auto p1 = m_str.find("}", p); + if (p1 != pstring::npos) + { + sl = p1 - p + 1; + fmt += m_str.substr(p+1, p1 - p - 1); + } } } - pstring::value_type pend = fmt.at(fmt.size() - 1); - if (pstring("duxo").find(cfmt_spec) != pstring::npos) + } + else + { + auto p1 = m_str.find("}", p); + if (p1 != pstring::npos) { - 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; + sl = p1 - p + 1; + fmt += ((m_arg>=10) ? m_str.substr(p+4, p1 - p - 4) : m_str.substr(p+3, p1 - p - 3)); } + } + 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; - 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); + } + 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); return *this; } -} // namespace plib +} diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h index cb9b59c01ce..9b7a85d8d8d 100644 --- a/src/lib/netlist/plib/pfmtlog.h +++ b/src/lib/netlist/plib/pfmtlog.h @@ -9,7 +9,6 @@ #include "pstring.h" #include "ptypes.h" -#include "putil.h" #include <limits> @@ -35,6 +34,7 @@ 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,6 +136,7 @@ struct ptype_traits<double> : ptype_traits_base<double> static char32_t fmt_spec() { return 'f'; } }; + template<> struct ptype_traits<char *> : ptype_traits_base<char *> { @@ -143,13 +144,6 @@ 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: @@ -157,57 +151,44 @@ public: : m_str(fmt), m_arg(0) { } - COPYASSIGNMOVE(pfmt, default) - ~pfmt() noexcept = default; + pfmt(const pfmt &rhs) : m_str(rhs.m_str), m_arg(rhs.m_arg) { } + + ~pfmt() + { + } 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); } @@ -222,13 +203,11 @@ private: }; template <class T, bool build_enabled = true> -class pfmt_writer_t +class pfmt_writer_t : plib::nocopyassignmove { 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 @@ -258,7 +237,7 @@ public: bool is_enabled() const { return m_enabled; } protected: - ~pfmt_writer_t() noexcept = default; + ~pfmt_writer_t() { } private: pfmt &xlog(pfmt &fmt) const { return fmt; } @@ -279,10 +258,7 @@ 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) { } - - COPYASSIGNMOVE(plog_channel, delete) - - ~plog_channel() noexcept = default; + ~plog_channel() { } protected: void vdowrite(const pstring &ls) const @@ -307,9 +283,7 @@ public: error(proxy), fatal(proxy) {} - - COPYASSIGNMOVE(plog_base, default) - virtual ~plog_base() noexcept = default; + virtual ~plog_base() {} plog_channel<T, plog_level::DEBUG, debug_enabled> debug; plog_channel<T, plog_level::INFO> info; @@ -319,7 +293,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 6a2179e0e6f..79f09cb4a46 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 (plib::startsWith(expr, "rpn:")) + if (expr.startsWith("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 (std::size_t i = 0; i < inputs.size(); i++) + for (unsigned 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; - bool err; - rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, err); + rc.m_param = cmd.as_double(&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(const pstring &v) +static int get_prio(pstring v) { if (v == "(" || v == ")") return 1; - else if (plib::left(v, 1) >= "a" && plib::left(v, 1) <= "z") + else if (v.left(1) >= "a" && v.left(1) <= "z") return 0; else if (v == "*" || v == "/") return 20; @@ -113,11 +113,12 @@ 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(plib::replace_all(expr, pstring(" "), pstring("")), sep)); + std::vector<pstring> sexpr(plib::psplit(expr.replace_all(" ",""), sep)); std::stack<pstring> opstk; std::vector<pstring> postfix; - for (std::size_t i = 0; i < sexpr.size(); i++) + //printf("dbg: %s\n", expr.c_str()); + for (unsigned i = 0; i < sexpr.size(); i++) { pstring &s = sexpr[i]; if (s=="(") @@ -181,15 +182,14 @@ 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) { - std::array<double, 20> stack = { 0 }; + double stack[20]; 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 fbb6c508333..7d5984f9d15 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 "pstate.h" #include "pstring.h" +#include "pstate.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 c2fee9c2f8e..5fefa658b83 100644 --- a/src/lib/netlist/plib/plists.h +++ b/src/lib/netlist/plib/plists.h @@ -12,8 +12,6 @@ #include "pstring.h" -#include <array> -#include <type_traits> #include <vector> namespace plib { @@ -31,13 +29,14 @@ class uninitialised_array_t { public: - using iterator = C *; - using const_iterator = const C *; + typedef C* iterator; + typedef const C* const_iterator; - uninitialised_array_t() noexcept = default; + uninitialised_array_t() + { + } - COPYASSIGNMOVE(uninitialised_array_t, delete) - ~uninitialised_array_t() noexcept + ~uninitialised_array_t() { for (std::size_t i=0; i<N; i++) (*this)[i].~C(); @@ -52,7 +51,7 @@ public: const C& operator[](const std::size_t &index) const noexcept { - return *reinterpret_cast<const C *>(&m_buf[index]); + return *reinterpret_cast<C *>(&m_buf[index]); } template<typename... Args> @@ -76,8 +75,7 @@ protected: private: /* ensure proper alignment */ - PALIGNAS_VECTOROPT() - std::array<typename std::aligned_storage<sizeof(C), alignof(C)>::type, N> m_buf; + typename std::aligned_storage<sizeof(C), alignof(C)>::type m_buf[N]; }; // ---------------------------------------------------------------------------------------- @@ -85,7 +83,6 @@ private: // the list allows insertions / deletions if used properly // ---------------------------------------------------------------------------------------- -#if 0 template <class LC> class linkedlist_t { @@ -155,10 +152,9 @@ public: void remove(const LC *elem) noexcept { auto p = &m_head; - while(*p != elem) + for ( ; *p != elem; p = &((*p)->m_next)) { //nl_assert(*p != nullptr); - p = &((*p)->m_next); } (*p) = elem->m_next; } @@ -170,105 +166,7 @@ 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 b381d96dca7..93c4076bac2 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); + auto ret = pstring(buf, pstring::UTF8); delete [] buf; return ret; } @@ -37,13 +37,18 @@ namespace plib { : options() , pout_strm() , perr_strm() - , pout(&pout_strm) - , perr(&perr_strm) + , pout(pout_strm) + , perr(perr_strm) { } - int app::main_utfX(int argc, char **argv) + app::~app() + { + + } + + 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 4f4be779251..e2f84b90de6 100644 --- a/src/lib/netlist/plib/pmain.h +++ b/src/lib/netlist/plib/pmain.h @@ -10,21 +10,20 @@ #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 <cwchar> #include <memory> +#include <cwchar> #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 @@ -37,10 +36,7 @@ namespace plib { { public: app(); - - COPYASSIGNMOVE(app, delete) - - virtual ~app() = default; + virtual ~app(); virtual pstring usage() = 0; virtual int execute() = 0; @@ -52,21 +48,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 = plib::make_unique<C>(); + auto a = std::unique_ptr<C>(new 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 deleted file mode 100644 index eab533688d7..00000000000 --- a/src/lib/netlist/plib/pmatrix2d.h +++ /dev/null @@ -1,85 +0,0 @@ -// 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 deleted file mode 100644 index f55807c86dc..00000000000 --- a/src/lib/netlist/plib/pmempool.h +++ /dev/null @@ -1,187 +0,0 @@ -// 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 f8a516df485..6559207f09d 100644 --- a/src/lib/netlist/plib/pomp.h +++ b/src/lib/netlist/plib/pomp.h @@ -11,8 +11,6 @@ #include "pconfig.h" -#include <cstddef> - #if HAS_OPENMP #include "omp.h" #endif @@ -20,39 +18,29 @@ namespace plib { namespace omp { -template <typename I, class T> -void for_static(const I start, const I end, const T &what) +template <class T> +void for_static(const int start, const int 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 (I i = start; i < end; i++) + for (int i = start; i < end; i++) what(i); } } -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) +inline void set_num_threads(const int threads) { #if HAS_OPENMP && USE_OPENMP omp_set_num_threads(threads); -#else - plib::unused_var(threads); #endif } -inline std::size_t get_max_threads() +inline int get_max_threads() { #if HAS_OPENMP && USE_OPENMP return omp_get_max_threads(); @@ -66,7 +54,7 @@ inline std::size_t 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 4a3d32c4723..910660acb3d 100644 --- a/src/lib/netlist/plib/poptions.cpp +++ b/src/lib/netlist/plib/poptions.cpp @@ -6,39 +6,77 @@ */ #include "poptions.h" -#include "pexception.h" -#include "ptypes.h" namespace plib { /*************************************************************************** Options ***************************************************************************/ - option_base::option_base(options &parent, const pstring &help) + option_base::option_base(options &parent, pstring help) : m_help(help) { parent.register_option(this); } - option::option(options &parent, const pstring &ashort, const pstring &along, const pstring &help, bool has_argument) + 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_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; @@ -47,88 +85,53 @@ namespace plib { } options::options() - : m_other_args(nullptr) { } - options::options(option **o) - : m_other_args(nullptr) + options::options(option *o[]) { int i=0; while (o[i] != nullptr) { - register_option(o[i]); + m_opts.push_back(o[i]); i++; } } - void options::register_option(option_base *opt) + options::~options() { - m_opts.push_back(opt); + m_opts.clear(); } - void options::check_consistency() + void options::register_option(option_base *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!" ); - } - } - } + m_opts.push_back(opt); } - int options::parse(int argc, char **argv) + int options::parse(int argc, char *argv[]) { - check_consistency(); - m_app = pstring(argv[0]); - bool seen_other_args = false; + m_app = pstring(argv[0], pstring::UTF8); for (int i=1; i<argc; ) { - pstring arg(argv[i]); + pstring arg(argv[i], pstring::UTF8); option *opt = nullptr; pstring opt_arg; bool has_equal_arg = false; - if (!seen_other_args && plib::startsWith(arg, "--")) + if (arg.startsWith("--")) { auto v = psplit(arg.substr(2),"="); - if (v.size() && v[0] != pstring("")) - { - 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 = getopt_long(v[0]); + has_equal_arg = (v.size() > 1); + if (has_equal_arg) { - opt = m_other_args; - seen_other_args = true; + for (unsigned j = 1; j < v.size() - 1; j++) + opt_arg = opt_arg + v[j] + "="; + opt_arg += v[v.size()-1]; } } - else if (!seen_other_args && plib::startsWith(arg, "-")) + else if (arg.startsWith("-")) { std::size_t p = 1; opt = getopt_short(arg.substr(p, 1)); @@ -141,11 +144,7 @@ namespace plib { } else { - seen_other_args = true; - if (m_other_args == nullptr) - return i; - opt = m_other_args; - i--; // we haven't had an option specifier; + return i; } if (opt == nullptr) return i; @@ -159,7 +158,7 @@ namespace plib { else { i++; // FIXME: are there more arguments? - if (opt->do_parse(pstring(argv[i])) != 0) + if (opt->do_parse(pstring(argv[i], pstring::UTF8)) != 0) return i - 1; } } @@ -174,7 +173,7 @@ namespace plib { return argc; } - pstring options::split_paragraphs(const pstring &text, unsigned width, unsigned indent, + pstring options::split_paragraphs(pstring text, unsigned width, unsigned indent, unsigned firstline_indent) { auto paragraphs = psplit(text,"\n"); @@ -182,13 +181,13 @@ namespace plib { for (auto &p : paragraphs) { - pstring line = plib::rpad(pstring(""), pstring(" "), firstline_indent); + pstring line = pstring("").rpad(" ", firstline_indent); for (auto &s : psplit(p, " ")) { if (line.length() + s.length() > width) { ret += line + "\n"; - line = plib::rpad(pstring(""), pstring(" "), indent); + line = pstring("").rpad(" ", indent); } line += s + " "; } @@ -197,8 +196,8 @@ namespace plib { return ret; } - pstring options::help(const pstring &description, const pstring &usage, - unsigned width, unsigned indent) const + pstring options::help(pstring description, pstring usage, + unsigned width, unsigned indent) { pstring ret; @@ -207,10 +206,6 @@ 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 = ""; @@ -226,20 +221,20 @@ namespace plib { if (opt->has_argument()) { line += "="; - auto *ol = dynamic_cast<option_str_limit_base *>(opt); + option_str_limit *ol = dynamic_cast<option_str_limit *>(opt); if (ol) { for (auto &v : ol->limit()) { line += v + "|"; } - line = plib::left(line, line.length() - 1); + line = line.left(line.length() - 1); } else line += "Value"; } } - line = plib::rpad(line, pstring(" "), indent - 2) + " "; + line = line.rpad(" ", indent - 2) + " "; if (line.length() > indent) { //ret += "TestGroup abc\n def gef\nxyz\n\n" ; @@ -255,7 +250,6 @@ namespace plib { if (grp->help() != "") ret += split_paragraphs(grp->help(), width, 4, 4) + "\n"; } } - // FIXME: other help ... pstring ex(""); for (auto & optbase : m_opts ) { @@ -272,22 +266,22 @@ namespace plib { return ret; } - option *options::getopt_short(const pstring &arg) const + option *options::getopt_short(pstring arg) { for (auto & optbase : m_opts) { auto opt = dynamic_cast<option *>(optbase); - if (opt && arg != "" && opt->short_opt() == arg) + if (opt && opt->short_opt() == arg) return opt; } return nullptr; } - option *options::getopt_long(const pstring &arg) const + option *options::getopt_long(pstring arg) { for (auto & optbase : m_opts) { auto opt = dynamic_cast<option *>(optbase); - if (opt && arg !="" && opt->long_opt() == arg) + if (opt && 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 086fe32fc8a..491ac0b4d91 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 "plists.h" #include "pstring.h" +#include "plists.h" #include "putil.h" namespace plib { @@ -24,12 +24,10 @@ class options; class option_base { public: - option_base(options &parent, const pstring &help); - virtual ~option_base() = default; - - COPYASSIGNMOVE(option_base, delete) + option_base(options &parent, pstring help); + virtual ~option_base(); - pstring help() const { return m_help; } + pstring help() { return m_help; } private: pstring m_help; }; @@ -37,10 +35,11 @@ private: class option_group : public option_base { public: - option_group(options &parent, const pstring &group, const pstring &help) + option_group(options &parent, pstring group, pstring help) : option_base(parent, help), m_group(group) { } + ~option_group(); - pstring group() const { return m_group; } + pstring group() { return m_group; } private: pstring m_group; }; @@ -48,10 +47,11 @@ private: class option_example : public option_base { public: - option_example(options &parent, const pstring &group, const pstring &help) + option_example(options &parent, pstring group, pstring help) : option_base(parent, help), m_example(group) { } + ~option_example(); - pstring example() const { return m_example; } + pstring example() { return m_example; } private: pstring m_example; }; @@ -60,7 +60,8 @@ private: class option : public option_base { public: - option(options &parent, const pstring &ashort, const pstring &along, const pstring &help, bool has_argument); + option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument); + ~option(); /* no_argument options will be called with "" argument */ @@ -88,177 +89,131 @@ private: class option_str : public option { public: - option_str(options &parent, const pstring &ashort, const pstring &along, const pstring &defval, const pstring &help) + option_str(options &parent, pstring ashort, pstring along, pstring defval, pstring help) : option(parent, ashort, along, help, true), m_val(defval) {} - pstring operator ()() const { return m_val; } + pstring operator ()() { return m_val; } protected: - int parse(const pstring &argument) override; + virtual int parse(const pstring &argument) override; private: pstring m_val; }; -class option_str_limit_base : public option +class option_str_limit : public option { public: - 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) + 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, ":")) { } - const std::vector<pstring> &limit() const { return m_limit; } + + pstring operator ()() { return m_val; } + const std::vector<pstring> &limit() { return m_limit; } protected: + virtual int parse(const pstring &argument) override; private: + pstring m_val; std::vector<pstring> m_limit; }; - -template <typename T> -class option_str_limit : public option_str_limit_base +class option_bool : public option { public: - 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; } + option_bool(options &parent, pstring ashort, pstring along, pstring help) + : option(parent, ashort, along, help, false), m_val(false) + {} - pstring as_string() const { return limit()[m_val]; } + bool operator ()() { return m_val; } protected: - 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; - } + virtual int parse(const pstring &argument) override; private: - T m_val; + bool m_val; }; -class option_bool : public option +class option_double : public option { public: - option_bool(options &parent, const pstring &ashort, const pstring &along, const pstring &help) - : option(parent, ashort, along, help, false), m_val(false) + option_double(options &parent, pstring ashort, pstring along, double defval, pstring help) + : option(parent, ashort, along, help, true), m_val(defval) {} - bool operator ()() const { return m_val; } + double operator ()() { return m_val; } protected: - int parse(const pstring &argument) override; + virtual int parse(const pstring &argument) override; private: - bool m_val; + double m_val; }; -template <typename T> -class option_num : public option +class option_long : public option { public: - 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) + option_long(options &parent, pstring ashort, pstring along, long defval, pstring help) + : option(parent, ashort, along, help, true), m_val(defval) {} - T operator ()() const { return m_val; } + long operator ()() { return m_val; } protected: - 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)); - } + virtual int parse(const pstring &argument) override; private: - T m_val; - T m_min; - T m_max; + long m_val; }; class option_vec : public option { public: - option_vec(options &parent, const pstring &ashort, const pstring &along, const pstring &help) + option_vec(options &parent, pstring ashort, pstring along, pstring help) : option(parent, ashort, along, help, true) {} - const std::vector<pstring> &operator ()() const { return m_val; } + std::vector<pstring> operator ()() { return m_val; } protected: - int parse(const pstring &argument) override; + virtual int parse(const pstring &argument) override; private: std::vector<pstring> m_val; }; -class option_args : public option_vec -{ -public: - option_args(options &parent, const pstring &help) - : option_vec(parent, "", "", help) - {} -}; - -class options : public nocopyassignmove +class options { public: options(); - explicit options(option **o); + explicit options(option *o[]); + + ~options(); void register_option(option_base *opt); - int parse(int argc, char **argv); + int parse(int argc, char *argv[]); - pstring help(const pstring &description, const pstring &usage, - unsigned width = 72, unsigned indent = 20) const; + pstring help(pstring description, pstring usage, + unsigned width = 72, unsigned indent = 20); - pstring app() const { return m_app; } + pstring app() { return m_app; } private: - static pstring split_paragraphs(const pstring &text, unsigned width, unsigned indent, + static pstring split_paragraphs(pstring text, unsigned width, unsigned indent, unsigned firstline_indent); - 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; + option *getopt_short(pstring arg); + option *getopt_long(pstring arg); 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 5e1a231da81..7547572192d 100644 --- a/src/lib/netlist/plib/pparser.cpp +++ b/src/lib/netlist/plib/pparser.cpp @@ -16,6 +16,16 @@ 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; @@ -24,7 +34,7 @@ pstring ptokenizer::currentline_str() void ptokenizer::skipeol() { - pstring::value_type c = getc(); + pstring::code_t c = getc(); while (c) { if (c == 10) @@ -39,11 +49,11 @@ void ptokenizer::skipeol() } -pstring::value_type ptokenizer::getc() +pstring::code_t ptokenizer::getc() { if (m_unget != 0) { - pstring::value_type c = m_unget; + pstring::code_t c = m_unget; m_unget = 0; return c; } @@ -56,11 +66,11 @@ pstring::value_type ptokenizer::getc() return 0; return '\n'; } - pstring::value_type c = *(m_px++); + pstring::code_t c = *(m_px++); return c; } -void ptokenizer::ungetc(pstring::value_type c) +void ptokenizer::ungetc(pstring::code_t c) { m_unget = c; } @@ -112,7 +122,6 @@ pstring ptokenizer::get_identifier_or_number() return tok.str(); } -// FIXME: combine into template double ptokenizer::get_number_double() { token_t tok = get_token(); @@ -120,8 +129,8 @@ double ptokenizer::get_number_double() { error(pfmt("Expected a number, got <{1}>")(tok.str()) ); } - bool err; - auto ret = plib::pstonum_ne<double>(tok.str(), err); + bool err = false; + double ret = tok.str().as_double(&err); if (err) error(pfmt("Expected a number, got <{1}>")(tok.str()) ); return ret; @@ -134,8 +143,8 @@ long ptokenizer::get_number_long() { error(pfmt("Expected a long int, got <{1}>")(tok.str()) ); } - bool err; - auto ret = plib::pstonum_ne<long>(tok.str(), err); + bool err = false; + long ret = tok.str().as_long(&err); if (err) error(pfmt("Expected a long int, got <{1}>")(tok.str()) ); return ret; @@ -173,7 +182,7 @@ ptokenizer::token_t ptokenizer::get_token() ptokenizer::token_t ptokenizer::get_token_internal() { /* skip ws */ - pstring::value_type c = getc(); + pstring::code_t c = getc(); while (m_whitespace.find(c) != pstring::npos) { c = getc(); @@ -263,31 +272,28 @@ void ptokenizer::error(const pstring &errs) // A simple preprocessor // ---------------------------------------------------------------------------------------- -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) +ppreprocessor::ppreprocessor(std::vector<define_t> *defines) +: m_ifflag(0), m_level(0), m_lineno(0) { - 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_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"); - if (defines != nullptr) - m_defines = *defines; m_defines.insert({"__PLIB_PREPROCESSOR__", define_t("__PLIB_PREPROCESSOR__", "1")}); + if (defines != nullptr) + { + for (auto & p : *defines) + { + m_defines.insert({p.m_name, p}); + } + } } void ppreprocessor::error(const pstring &err) @@ -295,42 +301,35 @@ 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 -int ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio) +double ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio) { - int val = 0; + double val; pstring tok=sexpr[start]; if (tok == "(") { start++; - val = expr(sexpr, start, /*prio*/ 255); + val = expr(sexpr, start, /*prio*/ 0); 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]; @@ -339,25 +338,36 @@ int ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, i // FIXME: catch error return val; } - else if (tok == "!") + else if (tok == "+") { - if (prio < 3) + if (prio > 10) return val; start++; - val = !expr(sexpr, start, 3); + val = val + expr(sexpr, start, 10); } - CHECKTOK2(*, 5) - CHECKTOK2(/, 5) - CHECKTOK2(+, 6) - CHECKTOK2(-, 6) - CHECKTOK2(==, 10) - CHECKTOK2(&&, 14) - CHECKTOK2(||, 15) - else + else if (tok == "-") { - // FIXME: error handling - val = plib::pstonum<decltype(val)>(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 == "==") + { + if (prio > 5) + return val; start++; + val = (val == expr(sexpr, start, 5)) ? 1.0 : 0.0; } } return val; @@ -366,7 +376,10 @@ int ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, i ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name) { auto idx = m_defines.find(name); - return (idx != m_defines.end()) ? &idx->second : nullptr; + if (idx != m_defines.end()) + return &idx->second; + else + return nullptr; } pstring ppreprocessor::replace_macros(const pstring &line) @@ -376,135 +389,78 @@ pstring ppreprocessor::replace_macros(const pstring &line) for (auto & elem : elems) { define_t *def = get_define(elem); - ret += (def != nullptr) ? def->m_replace : elem; + if (def != nullptr) + ret += def->m_replace; + else + ret += elem; } return ret; } -static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, const pstring &sep) +static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, pstring sep) { pstring ret(""); - for (std::size_t i = start; i < elems.size(); i++) + for (auto & elem : elems) { - ret += elems[i]; + ret += elem; ret += sep; } return ret; } -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 ppreprocessor::process_line(const pstring &line) { - 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 lt = line.replace_all("\t"," ").trim(); pstring ret; + m_lineno++; // FIXME ... revise and extend macro handling - if (plib::startsWith(lt, "#")) + if (lt.startsWith("#")) { std::vector<pstring> lti(psplit(lt, " ", true)); - if (lti[0] == "#if") + if (lti[0].equals("#if")) { m_level++; std::size_t start = 0; lt = replace_macros(lt); - std::vector<pstring> t(psplit(replace_all(lt.substr(3), pstring(" "), pstring("")), m_expr_sep)); - auto val = static_cast<int>(expr(t, start, 255)); + std::vector<pstring> t(psplit(lt.substr(3).replace_all(" ",""), m_expr_sep)); + int val = static_cast<int>(expr(t, start, 0)); if (val == 0) m_ifflag |= (1 << m_level); } - else if (lti[0] == "#ifdef") + else if (lti[0].equals("#ifdef")) { m_level++; if (get_define(lti[1]) == nullptr) m_ifflag |= (1 << m_level); } - else if (lti[0] == "#ifndef") + else if (lti[0].equals("#ifndef")) { m_level++; if (get_define(lti[1]) != nullptr) m_ifflag |= (1 << m_level); } - else if (lti[0] == "#else") + else if (lti[0].equals("#else")) { m_ifflag ^= (1 << m_level); } - else if (lti[0] == "#endif") + else if (lti[0].equals("#endif")) { m_ifflag &= ~(1 << m_level); m_level--; } - else if (lti[0] == "#include") + else if (lti[0].equals("#include")) { // ignore } - else if (lti[0] == "#pragma") + else if (lti[0].equals("#pragma")) { - if (m_ifflag == 0 && lti.size() > 3 && lti[1] == "NETLIST") + if (m_ifflag == 0 && lti.size() > 3 && lti[1].equals("NETLIST")) { - if (lti[2] == "warning") + if (lti[2].equals("warning")) error("NETLIST: " + catremainder(lti, 3, " ")); } } - else if (lti[0] == "#define") + else if (lti[0].equals("#define")) { if (m_ifflag == 0) { @@ -514,20 +470,28 @@ pstring ppreprocessor::process_line(pstring line) } } else - { - if (m_ifflag == 0) - error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(replace_macros(line))); - } + error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(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 1eca20e99ad..7ec517255c8 100644 --- a/src/lib/netlist/plib/pparser.h +++ b/src/lib/netlist/plib/pparser.h @@ -8,27 +8,20 @@ #ifndef PPARSER_H_ #define PPARSER_H_ +#include "pstring.h" #include "plists.h" #include "pstream.h" -#include "pstring.h" -#include <cstdint> #include <unordered_map> - +#include <cstdint> namespace plib { -class ptokenizer +class ptokenizer : nocopyassignmove { public: - 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) + explicit ptokenizer(plib::putf8_reader &strm); - virtual ~ptokenizer() = default; + virtual ~ptokenizer(); enum token_type { @@ -98,23 +91,22 @@ 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(const pstring &token) + token_id_t register_token(pstring token) { token_id_t ret(m_tokens.size()); m_tokens.emplace(token, ret); return ret; } - 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) + 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) { 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(); @@ -126,17 +118,17 @@ protected: private: void skipeol(); - pstring::value_type getc(); - void ungetc(pstring::value_type c); + pstring::code_t getc(); + void ungetc(pstring::code_t 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::value_type m_unget; + pstring::code_t m_unget; /* tokenizer stuff follows ... */ @@ -145,7 +137,7 @@ private: pstring m_number_chars_start; std::unordered_map<pstring, token_id_t> m_tokens; pstring m_whitespace; - pstring::value_type m_string; + pstring::code_t m_string; token_id_t m_tok_comment_start; token_id_t m_tok_comment_end; @@ -153,7 +145,7 @@ private: }; -class ppreprocessor : public pistream +class ppreprocessor : plib::nocopyassignmove { public: @@ -166,80 +158,29 @@ public: pstring m_replace; }; - 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; + explicit ppreprocessor(std::vector<define_t> *defines = nullptr); + virtual ~ppreprocessor() {} - - 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) - { - } + void process(putf8_reader &istrm, putf8_writer &ostrm); protected: - - 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); + double 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: - enum state_e - { - PROCESS, - LINE_CONTINUATION - }; - pstring process_line(pstring line); - pstring process_comments(pstring line); + pstring process_line(const pstring &line); - defines_map_type m_defines; + std::unordered_map<pstring, define_t> 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 9c5329cccde..dc151d5d6a6 100644 --- a/src/lib/netlist/plib/ppmf.h +++ b/src/lib/netlist/plib/ppmf.h @@ -10,8 +10,9 @@ #include "pconfig.h" -#include <cstdint> #include <utility> +#include <cstdint> + /* * @@ -69,8 +70,7 @@ namespace plib { using generic_function = void (*)(); template<typename MemberFunctionType> - mfp(MemberFunctionType mftp) // NOLINT(cppcoreguidelines-pro-type-member-init) - + mfp(MemberFunctionType mftp) : 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); - auto robject = reinterpret_cast<generic_class *>(object); + generic_class *robject = reinterpret_cast<generic_class *>(object); mfpo.convert_to_generic(rfunc, robject); func = reinterpret_cast<FunctionType>(rfunc); object = reinterpret_cast<ObjectType *>(robject); @@ -95,8 +95,7 @@ namespace plib { if (PHAS_PMF_INTERNAL == 1) { // apply the "this" delta to the object first - // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) - auto o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); + generic_class * 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)) @@ -242,28 +241,23 @@ namespace plib { { public: class generic_class; - - template <class C> - using MemberFunctionType = R (C::*)(Targs...); - pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {} - template<typename O> - pmfp(MemberFunctionType<O> mftp, O *object) + template<typename MemberFunctionType, typename O> + pmfp(MemberFunctionType mftp, O *object) : pmfp_base<R, Targs...>() { this->set(mftp, object); } - - template<typename O> - void set(MemberFunctionType<O> mftp, O *object) + template<typename MemberFunctionType, typename O> + void set(MemberFunctionType 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)...); } @@ -275,6 +269,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 3bd93ed4f8e..043033ed1ea 100644 --- a/src/lib/netlist/plib/pstate.cpp +++ b/src/lib/netlist/plib/pstate.cpp @@ -9,6 +9,17 @@ #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) { @@ -18,40 +29,46 @@ void state_manager_t::save_state_ptr(const void *owner, const pstring &stname, c void state_manager_t::remove_save_items(const void *owner) { - auto i = m_save.end(); - while (i != m_save.begin()) + for (auto i = m_save.begin(); i != m_save.end(); ) { - i--; if (i->get()->m_owner == owner) i = m_save.erase(i); + else + i++; } - i = m_custom.end(); - while (i > m_custom.begin()) + for (auto i = m_custom.begin(); i != m_custom.end(); ) { - 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(*this); + s->m_callback->on_pre_save(); } void state_manager_t::post_load() { for (auto & s : m_custom) - s->m_callback->on_post_load(*this); + s->m_callback->on_post_load(); } 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); } -} // namespace plib +state_manager_t::callback_t::~callback_t() +{ +} + + +} diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h index ac75ca6b69e..9757d6408b7 100644 --- a/src/lib/netlist/plib/pstate.h +++ b/src/lib/netlist/plib/pstate.h @@ -8,13 +8,11 @@ #ifndef PSTATE_H_ #define PSTATE_H_ -#include "palloc.h" #include "pstring.h" #include "ptypes.h" -#include <array> -#include <memory> #include <vector> +#include <memory> // ---------------------------------------------------------------------------------------- // state saving ... @@ -40,31 +38,32 @@ public: const bool is_custom; }; - template<typename T> - static datatype_t dtype() + template<typename T> struct datatype_f { - return datatype_t(sizeof(T), - plib::is_integral<T>::value || std::is_enum<T>::value, - std::is_floating_point<T>::value); - } + 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); + } + }; 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(state_manager_t &manager) = 0; - virtual void on_post_load(state_manager_t &manager) = 0; + virtual void on_pre_save() = 0; + virtual void on_post_load() = 0; protected: - callback_t() = default; - ~callback_t() = default; - COPYASSIGNMOVE(callback_t, default) }; struct entry_t { - using list_t = std::vector<plib::unique_ptr<entry_t>>; + using list_t = std::vector<std::unique_ptr<entry_t>>; entry_t(const pstring &stname, const datatype_t &dt, const void *owner, const std::size_t count, void *ptr) @@ -73,6 +72,8 @@ 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; @@ -81,49 +82,35 @@ public: void * m_ptr; }; - state_manager_t() = default; + state_manager_t(); + ~state_manager_t(); - 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, dtype<C>(), 1, &state); + save_state_ptr( owner, stname, datatype_f<C>::f(), 1, &state); } - 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) + template<typename C, std::size_t N> void save_item(const void *owner, C (&state)[N], const pstring &stname) { - save_state_ptr(owner, stname, dtype<C>(), N, &(state[0])); + save_state_ptr(owner, stname, datatype_f<C>::f(), 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, dtype<C>(), count, state); + save_state_ptr(owner, stname, datatype_f<C>::f(), count, state); } template<typename C> void save_item(const void *owner, std::vector<C> &v, const pstring &stname) { - 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()); + save_state(v.data(), owner, stname, v.size()); } void pre_save(); void post_load(); void remove_save_items(const void *owner); - 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; - } + const entry_t::list_t &save_list() const { return m_save; } void save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr); @@ -137,6 +124,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 a7acdaafb52..420f63c9e5e 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,14 +21,34 @@ 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 // ----------------------------------------------------------------------------- @@ -71,7 +91,7 @@ pifilestream::~pifilestream() } } -pifilestream::pos_type pifilestream::vread(value_type *buf, const pos_type n) +pifilestream::pos_type pifilestream::vread(void *buf, const pos_type n) { pos_type r = fread(buf, 1, n, static_cast<FILE *>(m_file)); if (r < n) @@ -99,7 +119,7 @@ void pifilestream::vseek(const pos_type n) throw file_e("Generic file operation failed: {}", m_filename); } -pifilestream::pos_type pifilestream::vtell() const +pifilestream::pos_type pifilestream::vtell() { long ret = ftell(static_cast<FILE *>(m_file)); if (ret < 0) @@ -120,6 +140,10 @@ pstdin::pstdin() /* nothing to do */ } +pstdin::~pstdin() +{ +} + // ----------------------------------------------------------------------------- // Output file stream // ----------------------------------------------------------------------------- @@ -156,11 +180,12 @@ pofilestream::~pofilestream() } } -void pofilestream::vwrite(const value_type *buf, const pos_type n) +void pofilestream::vwrite(const void *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); } @@ -179,7 +204,7 @@ void pofilestream::vseek(const pos_type n) } } -pstream::pos_type pofilestream::vtell() const +pstream::pos_type pofilestream::vtell() { std::ptrdiff_t ret = ftell(static_cast<FILE *>(m_file)); if (ret < 0) @@ -190,6 +215,11 @@ pstream::pos_type pofilestream::vtell() const return static_cast<pos_type>(ret); } +postringstream::~postringstream() +{ +} + + // ----------------------------------------------------------------------------- // pstderr: write to stderr // ----------------------------------------------------------------------------- @@ -203,6 +233,10 @@ pstderr::pstderr() { } +pstderr::~pstderr() +{ +} + // ----------------------------------------------------------------------------- // pstdout: write to stdout // ----------------------------------------------------------------------------- @@ -216,32 +250,35 @@ 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 char *>(mem)) + : pistream(FLAG_SEEKABLE), m_pos(0), m_len(len), m_mem(static_cast<const pstring::mem_t *>(mem)) { } -pimemstream::pimemstream() - : pistream(FLAG_SEEKABLE), m_pos(0), m_len(0), m_mem(static_cast<const char *>(nullptr)) +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(const pomemstream &ostrm) -: pistream(FLAG_SEEKABLE), m_pos(0), m_len(ostrm.size()), m_mem(reinterpret_cast<const char *>(ostrm.memory())) +pimemstream::~pimemstream() { } -pimemstream::pos_type pimemstream::vread(value_type *buf, const pos_type n) +pimemstream::pos_type pimemstream::vread(void *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, reinterpret_cast<char *>(buf)); + std::copy(m_mem + m_pos, m_mem + m_pos + ret, static_cast<char *>(buf)); m_pos += ret; } @@ -258,45 +295,78 @@ void pimemstream::vseek(const pos_type n) } -pimemstream::pos_type pimemstream::vtell() const +pimemstream::pos_type pimemstream::vtell() { return m_pos; } +pistringstream::~pistringstream() +{ +} + // ----------------------------------------------------------------------------- // Output memory stream // ----------------------------------------------------------------------------- pomemstream::pomemstream() -: postream(FLAG_SEEKABLE), m_pos(0), m_mem(1024) +: postream(FLAG_SEEKABLE), m_pos(0), m_capacity(1024), m_size(0) +{ + m_mem = palloc_array<char>(m_capacity); +} + +pomemstream::~pomemstream() { - m_mem.clear(); + pfree_array(m_mem); } -void pomemstream::vwrite(const value_type *buf, const pos_type n) +void pomemstream::vwrite(const void *buf, const pos_type n) { - if (m_pos + n >= m_mem.size()) - m_mem.resize(m_pos + 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); + } - std::copy(buf, buf + n, &m_mem[0] + m_pos); + std::copy(static_cast<const char *>(buf), static_cast<const char *>(buf) + n, m_mem + m_pos); m_pos += n; + m_size = std::max(m_pos, m_size); } void pomemstream::vseek(const pos_type n) { m_pos = n; - if (m_pos>=m_mem.size()) - m_mem.resize(m_pos); + 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); + } } -pstream::pos_type pomemstream::vtell() const +pstream::pos_type pomemstream::vtell() { return m_pos; } bool putf8_reader::readline(pstring &line) { - putf8string::code_t c = 0; + pstring::code_t c = 0; m_linebuf = ""; if (!this->readcode(c)) { @@ -308,14 +378,23 @@ bool putf8_reader::readline(pstring &line) if (c == 10) break; else if (c != 13) /* ignore CR */ - m_linebuf += putf8string(c); + m_linebuf += pstring(c); if (!this->readcode(c)) break; } - line = m_linebuf.c_str(); + line = m_linebuf; 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 { @@ -324,4 +403,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 93497eb1423..3e9ee99cba0 100644 --- a/src/lib/netlist/plib/pstream.h +++ b/src/lib/netlist/plib/pstream.h @@ -7,76 +7,46 @@ #ifndef PSTREAM_H_ #define PSTREAM_H_ - -#include "palloc.h" #include "pconfig.h" -#include "pexception.h" -#include "pfmtlog.h" #include "pstring.h" +#include "pfmtlog.h" +#include "pexception.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 +class pstream : nocopyassignmove { 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 seekp(const pos_type n) + void seek(const pos_type n) { - vseek(n); + return vseek(n); } - pos_type tellp() const + pos_type tell() { return vtell(); } protected: - pstream() : m_flags(0) - { - } explicit pstream(const unsigned flags) : m_flags(flags) { } - pstream(pstream &&src) noexcept = default; - - virtual ~pstream() = default; + ~pstream(); virtual void vseek(const pos_type n) = 0; - virtual pos_type vtell() const = 0; + virtual pos_type vtell() = 0; static constexpr unsigned FLAG_EOF = 0x01; static constexpr unsigned FLAG_SEEKABLE = 0x04; @@ -99,71 +69,51 @@ private: // pistream: input stream // ----------------------------------------------------------------------------- -template <typename T> -class pistream_base : public pstream +class pistream : public pstream { public: - using value_type = T; - - ~pistream_base() noexcept override = default; - - COPYASSIGN(pistream_base, delete) - pistream_base &operator=(pistream_base &&src) noexcept = delete; + virtual ~pistream(); bool eof() const { return ((flags() & FLAG_EOF) != 0); } - pos_type read(T *buf, const pos_type n) + pos_type read(void *buf, const pos_type n) { return vread(buf, n); } protected: - pistream_base() : pstream(0) {} - explicit pistream_base(const unsigned flags) : pstream(flags) {} - pistream_base(pistream_base &&src) noexcept : pstream(std::move(src)) {} - + explicit pistream(const unsigned flags) : pstream(flags) {} /* read up to n bytes from stream */ - virtual size_type vread(T *buf, const size_type n) = 0; -}; + virtual pos_type vread(void *buf, const pos_type n) = 0; -using pistream = pistream_base<char>; +}; // ----------------------------------------------------------------------------- // postream: output stream // ----------------------------------------------------------------------------- -#if !USE_CSTREAM -template <typename T> -class postream_base : public pstream +class postream : public pstream { public: - using value_type = T; - - postream_base() = default; - ~postream_base() noexcept override = default; - - COPYASSIGN(postream_base, delete) - postream_base &operator=(postream_base &&src) noexcept = delete; + virtual ~postream(); - void write(const T *buf, const size_type n) + void write(const void *buf, const pos_type n) { vwrite(buf, n); } -protected: - explicit postream_base(unsigned flags) : pstream(flags) {} - postream_base(postream_base &&src) noexcept : pstream(std::move(src)) {} + void write(pistream &strm); +protected: + explicit postream(unsigned flags) : pstream(flags) {} /* write n bytes to stream */ - virtual void vwrite(const T *buf, const size_type n) = 0; + virtual void vwrite(const void *buf, const pos_type n) = 0; private: }; -using postream = postream_base<char>; - // ----------------------------------------------------------------------------- // pomemstream: output string stream // ----------------------------------------------------------------------------- @@ -173,31 +123,22 @@ class pomemstream : public postream public: pomemstream(); + virtual ~pomemstream() override; - 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(); } + char *memory() const { return m_mem; } + pos_type size() const { return m_size; } protected: /* write n bytes to stream */ - void vwrite(const value_type *buf, const pos_type) override; - void vseek(const pos_type n) override; - pos_type vtell() const override; + virtual void vwrite(const void *buf, const pos_type) override; + virtual void vseek(const pos_type n) override; + virtual pos_type vtell() override; private: pos_type m_pos; - std::vector<char> m_mem; + pos_type m_capacity; + pos_type m_size; + char *m_mem; }; class postringstream : public postream @@ -205,26 +146,18 @@ class postringstream : public postream public: postringstream() : postream(0) { } - 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; + virtual ~postringstream() override; const pstring &str() { return m_buf; } protected: /* write n bytes to stream */ - void vwrite(const value_type *buf, const pos_type n) override + virtual void vwrite(const void *buf, const pos_type n) override { - m_buf += pstring(reinterpret_cast<const pstring::mem_t *>(buf), n); + m_buf += pstring(static_cast<const pstring::mem_t *>(buf), n, pstring::UTF8); } - void vseek(const pos_type n) override { unused_var(n); } - pos_type vtell() const override { return m_buf.size(); } + virtual void vseek(const pos_type n) override { } + virtual pos_type vtell() override { return m_buf.mem_t_size(); } private: pstring m_buf; @@ -238,28 +171,15 @@ class pofilestream : public postream { public: - 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; + explicit pofilestream(const pstring &fname); + virtual ~pofilestream() override; protected: pofilestream(void *file, const pstring &name, const bool do_close); /* write n bytes to stream */ - void vwrite(const value_type *buf, const pos_type n) override; - void vseek(const pos_type n) override; - pos_type vtell() const override; + virtual void vwrite(const void *buf, const pos_type n) override; + virtual void vseek(const pos_type n) override; + virtual pos_type vtell() override; private: void *m_file; @@ -273,17 +193,12 @@ private: // ----------------------------------------------------------------------------- // pstderr: write to stderr // ----------------------------------------------------------------------------- -#endif class pstderr : public pofilestream { public: pstderr(); - pstderr(pstderr &&src) noexcept = default; - pstderr &operator=(pstderr &&src) = delete; - COPYASSIGN(pstderr, delete) - - ~pstderr() noexcept override= default; + virtual ~pstderr(); }; // ----------------------------------------------------------------------------- @@ -294,11 +209,7 @@ class pstdout : public pofilestream { public: pstdout(); - pstdout(pstdout &&src) noexcept = default; - pstdout &operator=(pstdout &&src) = delete; - COPYASSIGN(pstdout, delete) - - ~pstdout() noexcept override = default; + virtual ~pstdout(); }; // ----------------------------------------------------------------------------- @@ -309,29 +220,16 @@ class pifilestream : public pistream { public: - 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; + explicit pifilestream(const pstring &fname); + virtual ~pifilestream() override; protected: pifilestream(void *file, const pstring &name, const bool do_close); /* read up to n bytes from stream */ - pos_type vread(value_type *buf, const pos_type n) override; - void vseek(const pos_type n) override; - pos_type vtell() const override; + virtual pos_type vread(void *buf, const pos_type n) override; + virtual void vseek(const pos_type n) override; + virtual pos_type vtell() override; private: void *m_file; @@ -351,10 +249,7 @@ class pstdin : public pifilestream public: pstdin(); - pstdin(pstdin &&src) noexcept = default; - pstdin &operator=(pstdin &&src) = delete; - COPYASSIGN(pstdin, delete) - ~pstdin() override = default; + virtual ~pstdin() override; }; // ----------------------------------------------------------------------------- @@ -366,36 +261,15 @@ 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); - - ~pimemstream() override = default; + virtual ~pimemstream() override; 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 */ - pos_type vread(value_type *buf, const pos_type n) override; - void vseek(const pos_type n) override; - pos_type vtell() const override; + virtual pos_type vread(void *buf, const pos_type n) override; + virtual void vseek(const pos_type n) override; + virtual pos_type vtell() override; private: pos_type m_pos; @@ -410,25 +284,12 @@ private: class pistringstream : public pimemstream { public: - 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; + explicit pistringstream(const pstring &str) : pimemstream(str.c_str(), str.mem_t_size()), m_str(str) { } + virtual ~pistringstream() override; private: /* only needed for a reference till destruction */ - const pstring m_str; + pstring m_str; }; // ----------------------------------------------------------------------------- @@ -437,84 +298,47 @@ private: /* this digests linux & dos/windows text files */ - -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 +class putf8_reader : plib::nocopyassignmove { public: + explicit putf8_reader(pistream &strm) : m_strm(strm) {} + virtual ~putf8_reader() {} - 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 eof() const { return m_strm.eof(); } bool readline(pstring &line); - bool readbyte1(pistream::value_type &b) + bool readbyte1(char &b) { - return (m_strm->read(&b, 1) == 1); + return (m_strm.read(&b, 1) == 1); } - bool readcode(putf8string::traits_type::code_t &c) + bool readcode(pstring::code_t &c) { - std::array<pistream::value_type, 4> b{0}; - if (m_strm->read(&b[0], 1) != 1) + char b[4]; + if (m_strm.read(&b[0], 1) != 1) return false; - const std::size_t l = putf8string::traits_type::codelen(reinterpret_cast<putf8string::traits_type::mem_t *>(&b)); + const std::size_t l = pstring::traits_type::codelen(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 = putf8string::traits_type::code(reinterpret_cast<putf8string::traits_type::mem_t *>(&b)); + c = pstring::traits_type::code(b); return true; } private: - 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); } + pistream &m_strm; + pstring m_linebuf; }; - // ----------------------------------------------------------------------------- // putf8writer_t: writer on top of ostream // ----------------------------------------------------------------------------- -class putf8_writer +class putf8_writer : plib::nocopyassignmove { public: - 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; + explicit putf8_writer(postream &strm) : m_strm(strm) {} + virtual ~putf8_writer() {} void writeline(const pstring &line) const { @@ -524,34 +348,24 @@ public: void write(const pstring &text) const { - // 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()); + m_strm.write(text.c_str(), text.mem_t_size()); } - void write(const pstring::value_type c) const + void write(const pstring::code_t c) const { - pstring t = pstring("") + c; - write(t); + write(pstring(c)); } 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) - : pfmt_writer_t() - , putf8_writer(strm) - { - } - - COPYASSIGNMOVE(putf8_fmt_writer, delete) - - ~putf8_fmt_writer() override = default; + explicit putf8_fmt_writer(postream &strm); + virtual ~putf8_fmt_writer() override; //protected: void vdowrite(const pstring &ls) const; @@ -563,29 +377,22 @@ private: // pbinary_writer_t: writer on top of ostream // ----------------------------------------------------------------------------- -class pbinary_writer +class pbinary_writer : plib::nocopyassignmove { public: explicit pbinary_writer(postream &strm) : m_strm(strm) {} - 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; + virtual ~pbinary_writer() {} template <typename T> - void write(const T &val) + void write(const T val) { - m_strm.write(reinterpret_cast<const postream::value_type *>(&val), sizeof(T)); + m_strm.write(&val, sizeof(T)); } void write(const pstring &s) { - 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); + write(s.mem_t_size()); + m_strm.write(s.c_str(), s.mem_t_size()); } template <typename T> @@ -593,38 +400,34 @@ public: { std::size_t sz = val.size(); write(sz); - m_strm.write(reinterpret_cast<const postream::value_type *>(val.data()), sizeof(T) * sz); + m_strm.write(val.data(), sizeof(T) * sz); } private: postream &m_strm; }; -class pbinary_reader +class pbinary_reader : plib::nocopyassignmove { public: explicit pbinary_reader(pistream &strm) : m_strm(strm) {} - 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; + virtual ~pbinary_reader() {} template <typename T> void read(T &val) { - m_strm.read(reinterpret_cast<pistream::value_type *>(&val), sizeof(T)); + m_strm.read(&val, sizeof(T)); } void read( pstring &s) { std::size_t sz = 0; read(sz); - std::vector<plib::string_info<pstring>::mem_t> buf(sz+1); - m_strm.read(buf.data(), sz); + pstring::mem_t *buf = new pstring::mem_t[sz+1]; + m_strm.read(buf, sz); buf[sz] = 0; - s = pstring(buf.data()); + s = pstring(buf, pstring::UTF8); + delete [] buf; } template <typename T> @@ -633,38 +436,13 @@ public: std::size_t sz = 0; read(sz); val.resize(sz); - m_strm.read(reinterpret_cast<pistream::value_type *>(val.data()), sizeof(T) * sz); + m_strm.read(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 c304f11d1fd..47d35d7c82f 100644 --- a/src/lib/netlist/plib/pstring.cpp +++ b/src/lib/netlist/plib/pstring.cpp @@ -10,8 +10,17 @@ #include "plists.h" #include <algorithm> -#include <atomic> #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; +} template<typename F> int pstring_t<F>::compare(const pstring_t &right) const @@ -58,6 +67,18 @@ 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; @@ -129,6 +150,114 @@ 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 c4caeab8e8f..cabce0e7b93 100644 --- a/src/lib/netlist/plib/pstring.h +++ b/src/lib/netlist/plib/pstring.h @@ -7,50 +7,45 @@ #ifndef PSTRING_H_ #define PSTRING_H_ -#include "ptypes.h" - -#include <cstring> -#include <exception> #include <iterator> -#include <limits> -#include <stdexcept> +#include <exception> #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 sub-optimal for the use-cases I encounter. +// strings in std:: which I would consider usuable 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: - using value_type = typename T::ref_value_type; + typedef typename T::ref_value_type value_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; + 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; - constexpr pstring_const_iterator() noexcept : p() { } + 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; } - // NOLINTNEXTLINE(cert-dcl21-cpp) - pstring_const_iterator operator++(int) & noexcept { pstring_const_iterator tmp(*this); operator++(); return tmp; } + pstring_const_iterator operator++(int) noexcept { pstring_const_iterator tmp(*this); operator++(); return tmp; } - 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; } + 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; } reference operator*() const noexcept { return *reinterpret_cast<pointer>(&(*p)); } pointer operator->() const noexcept { return reinterpret_cast<pointer>(&(*p)); } @@ -65,21 +60,18 @@ template <typename F> struct pstring_t { public: - using traits_type = F; + typedef F traits_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; + 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; - // FIXME: this is ugly - struct ref_value_type final + class 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; @@ -88,27 +80,37 @@ public: private: const mem_t m; }; - using const_reference = const ref_value_type &; - using reference = const_reference; + typedef const ref_value_type& const_reference; + typedef const_reference reference; + + enum enc_t + { + UTF8, + UTF16 + }; // simple construction/destruction - pstring_t() = default; - ~pstring_t() noexcept = default; + pstring_t() + { + } + ~pstring_t() + { + } // FIXME: Do something with encoding - pstring_t(const mem_t *string) + pstring_t(const mem_t *string, const enc_t enc) : m_str(string) { } - pstring_t(const mem_t *string, const size_type len) + pstring_t(const mem_t *string, const size_type len, const enc_t enc) : 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]) // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) + pstring_t(C (&string)[N]) { static_assert(N > 0,"pstring from array of length 0"); if (string[N-1] != 0) @@ -116,15 +118,17 @@ 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) + explicit pstring_t(const string_type &string, const enc_t enc) : m_str(string) { } - 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; + pstring_t(pstring_t &&string) + : m_str(string.m_str) + { } explicit pstring_t(code_t code) { @@ -140,8 +144,7 @@ public: *this += static_cast<code_t>(c); // FIXME: codepage conversion for u8 } - operator string_type () const { return m_str; } - + pstring_t &operator=(const pstring_t &string) { m_str = string.m_str; return *this; } template <typename T, class = typename std::enable_if<!std::is_same<T, pstring_t::traits_type>::value>::type> @@ -154,8 +157,8 @@ public: } // no non-const const_iterator for now - using iterator = pstring_const_iterator<pstring_t<F> >; - using const_iterator = pstring_const_iterator<pstring_t<F> >; + typedef pstring_const_iterator<pstring_t> iterator; + typedef pstring_const_iterator<pstring_t> const_iterator; iterator begin() { return iterator(m_str.begin()); } iterator end() { return iterator(m_str.end()); } @@ -198,26 +201,67 @@ 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 constexpr const size_type npos = static_cast<size_type>(-1); + static const size_type npos = static_cast<size_type>(-1); -private: +protected: string_type m_str; + +private: }; struct pu8_traits { - using mem_t = char; - using code_t = char; - using string_type = std::string; + typedef char mem_t; + typedef char code_t; + typedef std::string string_type; static std::size_t len(const string_type &p) { return p.size(); } - 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 std::size_t codelen(const mem_t *p) { return 1; } + static std::size_t codelen(const code_t 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]); } @@ -226,9 +270,9 @@ struct pu8_traits /* No checking, this may deliver invalid codes */ struct putf8_traits { - using mem_t = char; - using code_t = char32_t; - using string_type = std::string; + typedef char mem_t; + typedef char32_t code_t; + typedef std::string string_type; static std::size_t len(const string_type &p) { std::size_t ret = 0; @@ -241,7 +285,7 @@ struct putf8_traits } static std::size_t codelen(const mem_t *p) { - const auto p1 = reinterpret_cast<const unsigned char *>(p); + const unsigned char *p1 = reinterpret_cast<const unsigned char *>(p); if ((*p1 & 0x80) == 0x00) return 1; else if ((*p1 & 0xE0) == 0xC0) @@ -268,7 +312,7 @@ struct putf8_traits } static code_t code(const mem_t *p) { - const auto p1 = reinterpret_cast<const unsigned char *>(p); + const unsigned char *p1 = reinterpret_cast<const unsigned char *>(p); if ((*p1 & 0x80) == 0x00) return *p1; else if ((*p1 & 0xE0) == 0xC0) @@ -317,9 +361,9 @@ struct putf8_traits struct putf16_traits { - using mem_t = char16_t; - using code_t = char32_t; - using string_type = std::u16string; + typedef char16_t mem_t; + typedef char32_t code_t; + typedef std::u16string string_type; static std::size_t len(const string_type &p) { std::size_t ret = 0; @@ -327,7 +371,7 @@ struct putf16_traits while (i != p.end()) { // FIXME: check that size is equal - auto c = static_cast<uint16_t>(*i++); + uint16_t c = static_cast<uint16_t>(*i++); if (!((c & 0xd800) == 0xd800)) ret++; } @@ -335,7 +379,7 @@ struct putf16_traits } static std::size_t codelen(const mem_t *p) { - auto c = static_cast<uint16_t>(*p); + uint16_t c = static_cast<uint16_t>(*p); return ((c & 0xd800) == 0xd800) ? 2 : 1; } static std::size_t codelen(const code_t c) @@ -347,7 +391,7 @@ struct putf16_traits } static code_t code(const mem_t *p) { - auto c = static_cast<uint32_t>(*p++); + uint32_t c = static_cast<uint32_t>(*p++); if ((c & 0xd800) == 0xd800) { c = (c - 0xd800) << 10; @@ -357,7 +401,7 @@ struct putf16_traits } static void encode(code_t c, string_type &s) { - auto cu = static_cast<uint32_t>(c); + uint32_t cu = static_cast<uint32_t>(c); if (c > 0xffff) { //make a surrogate pair uint32_t t = ((cu - 0x10000) >> 10) + 0xd800; @@ -381,9 +425,9 @@ struct putf16_traits struct pwchar_traits { - using mem_t = wchar_t; - using code_t = char32_t; - using string_type = std::wstring; + typedef wchar_t mem_t; + typedef char32_t code_t; + typedef std::wstring string_type; static std::size_t len(const string_type &p) { if (sizeof(wchar_t) == 2) @@ -393,7 +437,7 @@ struct pwchar_traits while (i != p.end()) { // FIXME: check that size is equal - auto c = static_cast<uint32_t>(*i++); + uint32_t c = static_cast<uint32_t>(*i++); if (!((c & 0xd800) == 0xd800)) ret++; } @@ -407,7 +451,7 @@ struct pwchar_traits { if (sizeof(wchar_t) == 2) { - auto c = static_cast<uint16_t>(*p); + uint16_t c = static_cast<uint16_t>(*p); return ((c & 0xd800) == 0xd800) ? 2 : 1; } else @@ -426,7 +470,7 @@ struct pwchar_traits { if (sizeof(wchar_t) == 2) { - auto c = static_cast<uint32_t>(*p++); + uint32_t c = static_cast<uint32_t>(*p++); if ((c & 0xd800) == 0xd800) { c = (c - 0xd800) << 10; @@ -442,7 +486,7 @@ struct pwchar_traits { if (sizeof(wchar_t) == 2) { - auto cu = static_cast<uint32_t>(c); + uint32_t cu = static_cast<uint32_t>(c); if (c > 0xffff) { //make a surrogate pair uint32_t t = ((cu - 0x10000) >> 10) + 0xd800; @@ -475,280 +519,41 @@ extern template struct pstring_t<putf8_traits>; extern template struct pstring_t<putf16_traits>; extern template struct pstring_t<pwchar_traits>; -#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>; +typedef pstring_t<putf8_traits> pstring; +typedef pstring_t<putf16_traits> pu16string; +typedef pstring_t<pwchar_traits> pwstring; 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)); + return pstring(std::to_string(v), pstring::UTF8); } template<typename T> pwstring to_wstring(const T &v) { - 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); + return pwstring(std::to_wstring(v), pwstring::UTF16); } - - 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>> { - using argument_type = pstring_t<T>; - using result_type = std::size_t; + typedef pstring_t<T> argument_type; + typedef std::size_t result_type; result_type operator()(argument_type const& s) const { - const typename argument_type::mem_t *string = s.c_str(); + const pstring::mem_t *string = s.c_str(); result_type result = 5381; - for (typename argument_type::mem_t c = *string; c != 0; c = *string++) + for (pstring::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 deleted file mode 100644 index 32ccc4f7b0d..00000000000 --- a/src/lib/netlist/plib/ptime.h +++ /dev/null @@ -1,136 +0,0 @@ -// 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 bda62099150..0934a86fdf2 100644 --- a/src/lib/netlist/plib/ptypes.h +++ b/src/lib/netlist/plib/ptypes.h @@ -9,20 +9,10 @@ #define PTYPES_H_ #include "pconfig.h" +#include "pstring.h" -#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; \ +#include <limits> namespace plib { @@ -35,14 +25,14 @@ namespace plib template<> struct is_integral<INT128> { static constexpr bool value = true; }; template<> struct numeric_limits<UINT128> { - static constexpr UINT128 max() + static inline constexpr UINT128 max() { return ~((UINT128)0); } }; template<> struct numeric_limits<INT128> { - static constexpr INT128 max() + static inline constexpr INT128 max() { return (~((UINT128)0)) >> 1; } @@ -55,98 +45,56 @@ 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; - nocopyassign(nocopyassign &&) = default; - nocopyassign &operator=(nocopyassign &&) = default; + private: + nocopyassign(const nocopyassign &) = delete; + nocopyassign &operator=(const nocopyassign &) = delete; }; //============================================================ - // Avoid unused variable warnings + // penum - strongly typed enumeration //============================================================ - template<typename... Ts> - inline void unused_var(Ts&&...) {} - //============================================================ - // is_pow2 - //============================================================ - template <typename T> - constexpr bool is_pow2(T v) noexcept + struct penum_base { - 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 + protected: + static int from_string_int(const char *str, const char *x); + static pstring nthstr(int n, const char *str); + }; -//============================================================ -// Define a "has member" trait. -//============================================================ +} + +#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 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 b62cbf60865..c34102417ec 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 "plists.h" #include "ptypes.h" +#include "plists.h" -#include <algorithm> #include <cstdlib> -#include <cstring> +#include <algorithm> #include <initializer_list> +#include <cstring> namespace plib { @@ -17,7 +17,7 @@ namespace plib const pstring buildpath(std::initializer_list<pstring> list ) { pstring ret = ""; - for( const auto &elem : list ) + for( auto elem : list ) { if (ret == "") ret = elem; @@ -33,12 +33,12 @@ namespace plib const pstring environment(const pstring &var, const pstring &default_val) { - if (std::getenv(var.c_str()) == nullptr) + if (getenv(var.c_str()) == nullptr) return default_val; else - return pstring(std::getenv(var.c_str())); + return pstring(getenv(var.c_str()), pstring::UTF8); } - } // namespace util + } std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty) { @@ -64,36 +64,6 @@ 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 = ""; @@ -102,7 +72,7 @@ namespace plib auto i = str.begin(); while (i != str.end()) { - auto p = static_cast<std::size_t>(-1); + std::size_t 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)) @@ -122,7 +92,7 @@ namespace plib } else { - pstring::value_type c = *i; + pstring::code_t c = *i; col += c; i++; } @@ -161,8 +131,31 @@ namespace plib return cnt; return -1; } - std::string penum_base::nthstr(int n, const char *str) + pstring penum_base::nthstr(int n, const char *str) { - return psplit(str, ",", false)[static_cast<std::size_t>(n)]; + 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); } } // namespace plib diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h index e8145361d9d..8d59c0357e2 100644 --- a/src/lib/netlist/plib/putil.h +++ b/src/lib/netlist/plib/putil.h @@ -5,32 +5,27 @@ * */ -#ifndef PUTIL_H_ -#define PUTIL_H_ +#ifndef P_UTIL_H_ +#define P_UTIL_H_ #include "pstring.h" -#include <algorithm> #include <initializer_list> -#include <vector> - -#define PSTRINGIFY_HELP(y) # y -#define PSTRINGIFY(x) PSTRINGIFY_HELP(x) - +#include <algorithm> +#include <vector> // <<= needed by windows build 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, class T> - bool contains(C &con, const T &elem) + template <class C> + bool contains(C &con, const typename C::value_type &elem) { return std::find(con.begin(), con.end(), elem) != con.end(); } @@ -56,51 +51,7 @@ 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 @@ -118,41 +69,7 @@ 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 /* PUTIL_H_ */ +#endif /* P_UTIL_H_ */ diff --git a/src/lib/netlist/plib/vector_ops.h b/src/lib/netlist/plib/vector_ops.h deleted file mode 100644 index 8043c48f61c..00000000000 --- a/src/lib/netlist/plib/vector_ops.h +++ /dev/null @@ -1,151 +0,0 @@ -// 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_ */ |