summaryrefslogblamecommitdiffstatshomepage
path: root/src/lib/netlist/plib/putil.h
blob: 22abf637f876b5e9adf997ab054ca3068c41d37c (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                               
 

                
 



                 
                   
                       
                    
 
                    
                           
                 
 


                                        
























                                                                                                


                                                                 
 

              
 





                                                                                  






                                                                        
                                                                                    


                                                                                   
                                                                                          





                                                                         
 
                                                       











                                     





                                                                             





                                                                  
                                               








                                                                   






                                                                                 




                                                        
                                                                


                                                     
                                                             












                                                                                   



                                                              






                                                         
                                                          

























                                                                         
                                      
















                                                                        

                      

                                                          

                                                                                    
                           
 

                           

                                                    



                                                                                    
                                                                                       
                                  
                                                                               


                                                                          

                                                                                  




                                                                                                   
                                                                                           

                 




                                                                                        

                                


                              
                                                                              
 
                                                                                         
 
                                  

          



                                                                                                   

                                                                                                         



                                                                  






                                                                      

                                                                                 







                                                  
                                                                                            
                                                           
                                                                

                                                                                                    


                                                                                           
                                            
                                                                          
                   





                                                                        
 
                  
// license:GPL-2.0+
// copyright-holders:Couriersud

#ifndef PUTIL_H_
#define PUTIL_H_

///
/// \file putil.h
///

#include "palloc.h"
#include "pexception.h"
#include "pstring.h"

#include <algorithm>
#include <initializer_list>
#include <vector>

#define PSTRINGIFY_HELP(y) # y
#define PSTRINGIFY(x) PSTRINGIFY_HELP(x)

#define PNARGS_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
#define PNARGS(...) PNARGS_(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

#define PCONCAT_(a, b) a ## b
#define PCONCAT(a, b) PCONCAT_(a, b)

#define PSTRINGIFY_1(x)                     #x
#define PSTRINGIFY_2(x, x2)                 #x, #x2
#define PSTRINGIFY_3(x, ...)                #x, PSTRINGIFY_2(__VA_ARGS__)
#define PSTRINGIFY_4(x, ...)                #x, PSTRINGIFY_3(__VA_ARGS__)
#define PSTRINGIFY_5(x, ...)                #x, PSTRINGIFY_4(__VA_ARGS__)
#define PSTRINGIFY_6(x, ...)                #x, PSTRINGIFY_5(__VA_ARGS__)
#define PSTRINGIFY_7(x, ...)                #x, PSTRINGIFY_6(__VA_ARGS__)
#define PSTRINGIFY_8(x, ...)                #x, PSTRINGIFY_7(__VA_ARGS__)
#define PSTRINGIFY_9(x, ...)                #x, PSTRINGIFY_8(__VA_ARGS__)
#define PSTRINGIFY_10(x, ...)               #x, PSTRINGIFY_9(__VA_ARGS__)
#define PSTRINGIFY_11(x, ...)               #x, PSTRINGIFY_10(__VA_ARGS__)
#define PSTRINGIFY_12(x, ...)               #x, PSTRINGIFY_11(__VA_ARGS__)
#define PSTRINGIFY_13(x, ...)               #x, PSTRINGIFY_12(__VA_ARGS__)
#define PSTRINGIFY_14(x, ...)               #x, PSTRINGIFY_13(__VA_ARGS__)
#define PSTRINGIFY_15(x, ...)               #x, PSTRINGIFY_14(__VA_ARGS__)
#define PSTRINGIFY_16(x, ...)               #x, PSTRINGIFY_15(__VA_ARGS__)

#define PSTRINGIFY_VA(...) PCONCAT(PSTRINGIFY_, PNARGS(__VA_ARGS__))(__VA_ARGS__)

// FIXME:: __FUNCTION__ may be not be supported by all compilers.

#define PSOURCELOC() plib::source_location(__FILE__, __LINE__)

namespace plib
{

	/// \brief Source code locations.
	///
	/// The c++20 draft for source locations is based on const char * strings.
	/// It is thus only suitable for c++ source code and not for programmatic
	/// parsing of files. This class is a replacement for dynamic use cases.
	///
	struct source_location
	{
		source_location() noexcept
		: m_file("unknown"), m_func(m_file), m_line(0), m_col(0)
		{ }

		source_location(pstring file, unsigned line) noexcept
		: m_file(std::move(file)), m_func("unknown"), m_line(line), m_col(0)
		{ }

		source_location(pstring file, pstring func, unsigned line) noexcept
		: m_file(std::move(file)), m_func(std::move(func)), m_line(line), m_col(0)
		{ }

		unsigned line() const noexcept { return m_line; }
		unsigned column() const noexcept { return m_col; }
		pstring file_name() const noexcept { return m_file; }
		pstring function_name() const noexcept { return m_func; }

		source_location &operator ++() noexcept
		{
			++m_line;
			return *this;
		}

	private:
		pstring m_file;
		pstring m_func;
		unsigned m_line;
		unsigned m_col;
	};

	/// \brief Base source class.
	///
	/// Pure virtual class all other source implementations are based on.
	/// Sources provide an abstraction to read input from a variety of
	/// sources, e.g. files, memory, remote locations.
	///
	class psource_t
	{
	public:

		using stream_ptr = plib::unique_ptr<std::istream>;

		psource_t() noexcept = default;

		COPYASSIGNMOVE(psource_t, delete)

		virtual ~psource_t() noexcept = default;

		virtual stream_ptr stream(const pstring &name) = 0;
	private:
	};

	/// \brief Generic string source.
	///
	/// Will return the given string when name matches.
	/// Is used in preprocessor code to eliminate inclusion of certain files.
	///
	/// \tparam TS base stream class. Default is psource_t
	///
	template <typename TS = psource_t>
	class psource_str_t : public TS
	{
	public:
		psource_str_t(pstring name, pstring str)
		: m_name(std::move(name)), m_str(std::move(str))
		{}

		COPYASSIGNMOVE(psource_str_t, delete)
		~psource_str_t() noexcept override = default;

		typename TS::stream_ptr stream(const pstring &name) override
		{
			if (name == m_name)
				return plib::make_unique<std::stringstream>(m_str);
			else
				return typename TS::stream_ptr(nullptr);
		}
	private:
		pstring m_name;
		pstring m_str;
	};

	/// \brief Generic sources collection.
	///
	/// \tparam TS base stream class. Default is psource_t
	///
	template <typename TS = psource_t>
	class psource_collection_t
	{
	public:
		using source_type = plib::unique_ptr<TS>;
		using list_t = std::vector<source_type>;

		psource_collection_t() noexcept = default;

		COPYASSIGNMOVE(psource_collection_t, delete)
		virtual ~psource_collection_t() noexcept = default;

		void add_source(source_type &&src)
		{
			m_collection.push_back(std::move(src));
		}

		template <typename S = TS>
		typename S::stream_ptr get_stream(pstring name)
		{
			for (auto &s : m_collection)
			{
				auto source(dynamic_cast<S *>(s.get()));
				if (source)
				{
					auto strm = source->stream(name);
					if (strm)
						return strm;
				}
			}
			return typename S::stream_ptr(nullptr);
		}

		template <typename S, typename F>
		bool for_all(F lambda)
		{
			for (auto &s : m_collection)
			{
				auto source(dynamic_cast<S *>(s.get()));
				if (source)
				{
					if (lambda(source))
						return true;
				}
			}
			return false;
		}

	private:
		list_t m_collection;
	};

	namespace util
	{
		pstring basename(const pstring &filename);
		pstring path(const pstring &filename);
		pstring buildpath(std::initializer_list<pstring> list );
		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)
		{
			return std::find(con.begin(), con.end(), elem) != con.end();
		}

		static constexpr const std::size_t npos = static_cast<std::size_t>(-1);
		template <class C>
		std::size_t indexof(C &con, const typename C::value_type &elem)
		{
			auto it = std::find(con.begin(), con.end(), elem);
			if (it != con.end())
				return static_cast<std::size_t>(it - con.begin());
			return npos;
		}

		template <class C>
		void insert_at(C &con, const std::size_t index, const typename C::value_type &elem)
		{
			con.insert(con.begin() + static_cast<std::ptrdiff_t>(index), elem);
		}

		template <class C>
		void remove(C &con, const typename C::value_type &elem)
		{
			con.erase(std::remove(con.begin(), con.end(), elem), con.end());
		}
	} // namespace container

	template <class C>
	struct indexed_compare
	{
		explicit indexed_compare(const C& target): m_target(target) {}

		bool operator()(int a, int b) const { return m_target[a] < m_target[b]; }

		const C& m_target;
	};

	// ----------------------------------------------------------------------------------------
	// string list
	// ----------------------------------------------------------------------------------------

	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 pstring &str, const pstring &x);
		static std::string nthstr(int n, const pstring &str);
	};

} // namespace plib

#define P_ENUM(ename, ...) \
	struct ename : public plib::penum_base { \
		enum E { __VA_ARGS__ }; \
		ename (E v) : m_v(v) { } \
		template <typename T> explicit ename(T val) { m_v = static_cast<E>(val); } \
		bool set_from_string (const pstring &s) { \
			int f = from_string_int(strings(), s); \
			if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
		} \
		operator E() const noexcept {return m_v;} \
		bool operator==(const ename &rhs) const noexcept {return m_v == rhs.m_v;} \
		bool operator==(const E &rhs) const noexcept {return m_v == rhs;} \
		std::string name() const { \
			return nthstr(static_cast<int>(m_v), strings()); \
		} \
		private: E m_v; \
		static pstring strings() {\
			static const pstring lstrings = # __VA_ARGS__; \
			return lstrings; \
		} \
	};

#endif // PUTIL_H_