<commit_before>#pragma once
/*
* Covariant Mozart Utility Library: Any
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2017 Michael Lee(李登淳)
* Email: China-LDC@outlook.com
* Github: https://github.com/mikecovlee
* Website: http://ldc.atd3.cn
*
* Version: 17.4.2
*/
#include "./base.hpp"
#include <functional>
#include <iostream>

namespace std {
	template<typename T> std::string to_string(const T&)
	{
		throw cov::error("E000D");
	}
	template<> std::string to_string<std::string>(const std::string& str)
	{
		return str;
	}
	template<> std::string to_string<bool>(const bool& v)
	{
		if(v)
			return "true";
		else
			return "false";
	}
}

namespace cov {
	template<typename _Tp> class compare_helper {
		template<typename T,typename X=bool>struct matcher;
		template<typename T> static constexpr bool match(T*)
		{
			return false;
		}
		template<typename T> static constexpr bool match(matcher < T, decltype(std::declval<T>()==std::declval<T>()) > *)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct compare_if;
	template<typename T>struct compare_if<T,true> {
		static bool compare(const T& a,const T& b)
		{
			return a==b;
		}
	};
	template<typename T>struct compare_if<T,false> {
		static bool compare(const T& a,const T& b)
		{
			return &a==&b;
		}
	};
	template<typename T>bool compare(const T& a,const T& b)
	{
		return compare_if<T,compare_helper<T>::value>::compare(a,b);
	}
	template<typename _Tp> class hash_helper {
		template<typename T,decltype(&std::hash<T>::operator()) X>struct matcher;
		template<typename T> static constexpr bool match(T*)
		{
			return false;
		}
		template<typename T> static constexpr bool match(matcher<T,&std::hash<T>::operator()>*)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct hash_if;
	template<typename T>struct hash_if<T,true> {
		static std::size_t hash(const T& val)
		{
			static std::hash<T> gen;
			return gen(val);
		}
	};
	template<typename T>struct hash_if<T,false> {
		static std::size_t hash(const T& val)
		{
			throw cov::error("E000F");
		}
	};
	template<typename T>std::size_t hash(const T& val)
	{
		return hash_if<T,hash_helper<T>::value>::hash(val);
	}
	class any final {
		class baseHolder {
		public:
			baseHolder() = default;
			virtual ~ baseHolder() = default;
			virtual const std::type_info& type() const = 0;
			virtual baseHolder* duplicate() = 0;
			virtual bool compare(const baseHolder *) const = 0;
			virtual std::string to_string() const = 0;
			virtual std::size_t hash() const = 0;
		};
		template < typename T > class holder:public baseHolder {
		protected:
			T mDat;
		public:
			holder() = default;
			holder(const T& dat):mDat(dat) {}
			virtual ~ holder() = default;
			virtual const std::type_info& type() const override
			{
				return typeid(T);
			}
			virtual baseHolder* duplicate() override
			{
				return new holder(mDat);
			}
			virtual bool compare(const baseHolder* obj) const override
			{
				if (obj->type()==this->type()) {
					const holder<T>* ptr=dynamic_cast<const holder<T>*>(obj);
					return ptr!=nullptr?cov::compare(mDat,ptr->data()):false;
				}
				return false;
			}
			virtual std::string to_string() const override
			{
				return std::to_string(mDat);
			}
			virtual std::size_t hash() const override
			{
				return cov::hash<T>(mDat);
			}
			T& data()
			{
				return mDat;
			}
			const T& data() const
			{
				return mDat;
			}
			void data(const T& dat)
			{
				mDat = dat;
			}
		};
		using size_t=unsigned long;
		struct proxy {
			size_t refcount=1;
			baseHolder* data=nullptr;
			proxy()=default;
			proxy(size_t rc,baseHolder* d):refcount(rc),data(d) {}
			~proxy()
			{
				delete data;
			}
		};
		proxy* mDat=nullptr;
		proxy* duplicate() const noexcept
		{
			if(mDat!=nullptr) {
				++mDat->refcount;
			}
			return mDat;
		}
		void recycle() noexcept
		{
			if(mDat!=nullptr) {
				--mDat->refcount;
				if(mDat->refcount==0) {
					delete mDat;
					mDat=nullptr;
				}
			}
		}
	public:
		void swap(any& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void swap(any&& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void clone() noexcept
		{
			if(mDat!=nullptr) {
				proxy* dat=new proxy(1,mDat->data->duplicate());
				recycle();
				mDat=dat;
			}
		}
		bool usable() const noexcept
		{
			return mDat!=nullptr;
		}
		any()=default;
		template<typename T> any(const T & dat):mDat(new proxy(1,new holder < T > (dat))) {}
		any(const any & v):mDat(v.duplicate()) {}
		any(any&& v) noexcept
		{
			swap(std::forward<any>(v));
		}
		~any()
		{
			recycle();
		}
		const std::type_info& type() const
		{
			return this->mDat!=nullptr?this->mDat->data->type():typeid(void);
		}
		std::string to_string() const
		{
			if(this->mDat==nullptr)
				return "Null";
			return this->mDat->data->to_string();
		}
		std::size_t hash() const
		{
			if(this->mDat==nullptr)
				return cov::hash<void*>(nullptr);
			return this->mDat->data->hash();
		}
		bool is_same(const any& obj) const
		{
			return this->mDat==obj.mDat;
		}
		any& operator=(const any& var)
		{
			if(&var!=this) {
				recycle();
				mDat=var.duplicate();
			}
			return *this;
		}
		any& operator=(any&& var) noexcept
		{
			if(&var!=this)
				swap(std::forward<any>(var));
			return *this;
		}
		bool operator==(const any& var) const
		{
			return usable()?this->mDat->data->compare(var.mDat->data):!var.usable();
		}
		bool operator!=(const any& var)const
		{
			return usable()?!this->mDat->data->compare(var.mDat->data):var.usable();
		}
		template<typename T> T& val(bool raw=false)
		{
			if(typeid(T)!=this->type())
				throw cov::error("E0006");
			if(this->mDat==nullptr)
				throw cov::error("E0005");
			if(!raw)
				clone();
			return dynamic_cast<holder<T>*>(this->mDat->data)->data();
		}
		template<typename T> const T& val(bool raw=false) const
		{
			if(typeid(T)!=this->type())
				throw cov::error("E0006");
			if(this->mDat==nullptr)
				throw cov::error("E0005");
			return dynamic_cast<const holder<T>*>(this->mDat->data)->data();
		}
		template<typename T> const T& const_val() const
		{
			if(typeid(T)!=this->type())
				throw cov::error("E0006");
			if(this->mDat==nullptr)
				throw cov::error("E0005");
			return dynamic_cast<const holder<T>*>(this->mDat->data)->data();
		}
		template<typename T> operator const T&() const
		{
			return this->const_val<T>();
		}
		void assign(const any& obj,bool raw=false)
		{
			if(&obj!=this&&obj.mDat!=mDat) {
				if(mDat!=nullptr&&obj.mDat!=nullptr&&raw) {
					delete mDat->data;
					mDat->data=obj.mDat->data->duplicate();
				} else {
					recycle();
					if(obj.mDat!=nullptr)
						mDat=new proxy(1,obj.mDat->data->duplicate());
					else
						mDat=nullptr;
				}
			}
		}
		template<typename T> void assign(const T& dat,bool raw=false)
		{
			if(raw) {
				delete mDat->data;
				mDat->data=new holder<T>(dat);
			} else {
				recycle();
				mDat=new proxy(1,new holder<T>(dat));
			}
		}
		template<typename T> any & operator=(const T& dat)
		{
			assign(dat);
			return *this;
		}
	};
	template<int N> class any::holder<char[N]>:public any::holder<std::string> {
	public:
		using holder<std::string>::holder;
	};
	template<> class any::holder<std::type_info>:public any::holder<std::type_index> {
	public:
		using holder<std::type_index>::holder;
	};
}

std::ostream& operator<<(std::ostream& out,const cov::any& val)
{
	out<<val.to_string();
	return out;
}

namespace std {
	template<> struct hash<cov::any> {
		std::size_t operator()(const cov::any& val) const
		{
			return val.hash();
		}
	};
}
<commit_msg>更新cov::any<commit_after>#pragma once
/*
* Covariant Mozart Utility Library: Any
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2017 Michael Lee(李登淳)
* Email: China-LDC@outlook.com
* Github: https://github.com/mikecovlee
* Website: http://ldc.atd3.cn
*
* Version: 17.4.3
*/
#include "./base.hpp"
#include <functional>
#include <iostream>

namespace std {
	template<typename T> std::string to_string(const T&)
	{
		throw cov::error("E000D");
	}
	template<> std::string to_string<std::string>(const std::string& str)
	{
		return str;
	}
	template<> std::string to_string<bool>(const bool& v)
	{
		if(v)
			return "true";
		else
			return "false";
	}
}

namespace cov {
	template<typename _Tp> class compare_helper {
		template<typename T,typename X=bool>struct matcher;
		template<typename T> static constexpr bool match(T*)
		{
			return false;
		}
		template<typename T> static constexpr bool match(matcher < T, decltype(std::declval<T>()==std::declval<T>()) > *)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct compare_if;
	template<typename T>struct compare_if<T,true> {
		static bool compare(const T& a,const T& b)
		{
			return a==b;
		}
	};
	template<typename T>struct compare_if<T,false> {
		static bool compare(const T& a,const T& b)
		{
			return &a==&b;
		}
	};
	template<typename T>bool compare(const T& a,const T& b)
	{
		return compare_if<T,compare_helper<T>::value>::compare(a,b);
	}
	template<typename _Tp> class hash_helper {
		template<typename T,decltype(&std::hash<T>::operator()) X>struct matcher;
		template<typename T> static constexpr bool match(T*)
		{
			return false;
		}
		template<typename T> static constexpr bool match(matcher<T,&std::hash<T>::operator()>*)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct hash_if;
	template<typename T>struct hash_if<T,true> {
		static std::size_t hash(const T& val)
		{
			static std::hash<T> gen;
			return gen(val);
		}
	};
	template<typename T>struct hash_if<T,false> {
		static std::size_t hash(const T& val)
		{
			throw cov::error("E000F");
		}
	};
	template<typename T>std::size_t hash(const T& val)
	{
		return hash_if<T,hash_helper<T>::value>::hash(val);
	}
	template<typename T>void detach(T& val)
	{
		// Do something if you want when data is copying.
	}
	class any final {
		class baseHolder {
		public:
			baseHolder() = default;
			virtual ~ baseHolder() = default;
			virtual const std::type_info& type() const = 0;
			virtual baseHolder* duplicate() = 0;
			virtual bool compare(const baseHolder *) const = 0;
			virtual std::string to_string() const = 0;
			virtual std::size_t hash() const = 0;
			virtual void detach() = 0;
		};
		template < typename T > class holder:public baseHolder {
		protected:
			T mDat;
		public:
			holder() = default;
			template<typename...ArgsT>holder(ArgsT&&...args):mDat(std::forward<ArgsT>(args)...) {}
			virtual ~ holder() = default;
			virtual const std::type_info& type() const override
			{
				return typeid(T);
			}
			virtual baseHolder* duplicate() override
			{
				return new holder(mDat);
			}
			virtual bool compare(const baseHolder* obj) const override
			{
				if (obj->type()==this->type()) {
					const holder<T>* ptr=dynamic_cast<const holder<T>*>(obj);
					return ptr!=nullptr?cov::compare(mDat,ptr->data()):false;
				}
				return false;
			}
			virtual std::string to_string() const override
			{
				return std::to_string(mDat);
			}
			virtual std::size_t hash() const override
			{
				return cov::hash<T>(mDat);
			}
			virtual void detach() override
			{
				cov::detach(mDat);
			}
			T& data()
			{
				return mDat;
			}
			const T& data() const
			{
				return mDat;
			}
			void data(const T& dat)
			{
				mDat = dat;
			}
		};
		using size_t=unsigned long;
		struct proxy {
			size_t refcount=1;
			baseHolder* data=nullptr;
			proxy()=default;
			proxy(size_t rc,baseHolder* d):refcount(rc),data(d) {}
			~proxy()
			{
				delete data;
			}
		};
		proxy* mDat=nullptr;
		proxy* duplicate() const noexcept
		{
			if(mDat!=nullptr) {
				++mDat->refcount;
			}
			return mDat;
		}
		void recycle() noexcept
		{
			if(mDat!=nullptr) {
				--mDat->refcount;
				if(mDat->refcount==0) {
					delete mDat;
					mDat=nullptr;
				}
			}
		}
		any(proxy* dat):mDat(dat) {}
	public:
		void swap(any& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void swap(any&& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void clone() noexcept
		{
			if(mDat!=nullptr) {
				proxy* dat=new proxy(1,mDat->data->duplicate());
				recycle();
				mDat=dat;
			}
		}
		bool usable() const noexcept
		{
			return mDat!=nullptr;
		}
		template<typename T,typename...ArgsT>static any make(ArgsT&&...args)
		{
			return any(new proxy(1,new holder<T>(std::forward<ArgsT>(args)...)));
		}
		any()=default;
		template<typename T> any(const T & dat):mDat(new proxy(1,new holder<T> (dat))) {}
		any(const any & v):mDat(v.duplicate()) {}
		any(any&& v) noexcept
		{
			swap(std::forward<any>(v));
		}
		~any()
		{
			recycle();
		}
		const std::type_info& type() const
		{
			return this->mDat!=nullptr?this->mDat->data->type():typeid(void);
		}
		std::string to_string() const
		{
			if(this->mDat==nullptr)
				return "Null";
			return this->mDat->data->to_string();
		}
		std::size_t hash() const
		{
			if(this->mDat==nullptr)
				return cov::hash<void*>(nullptr);
			return this->mDat->data->hash();
		}
		void detach()
		{
			if(this->mDat!=nullptr)
				this->mDat->data->detach();
		}
		bool is_same(const any& obj) const
		{
			return this->mDat==obj.mDat;
		}
		any& operator=(const any& var)
		{
			if(&var!=this) {
				recycle();
				mDat=var.duplicate();
			}
			return *this;
		}
		any& operator=(any&& var) noexcept
		{
			if(&var!=this)
				swap(std::forward<any>(var));
			return *this;
		}
		bool operator==(const any& var) const
		{
			return usable()?this->mDat->data->compare(var.mDat->data):!var.usable();
		}
		bool operator!=(const any& var)const
		{
			return usable()?!this->mDat->data->compare(var.mDat->data):var.usable();
		}
		template<typename T> T& val(bool raw=false)
		{
			if(typeid(T)!=this->type())
				throw cov::error("E0006");
			if(this->mDat==nullptr)
				throw cov::error("E0005");
			if(!raw)
				clone();
			return dynamic_cast<holder<T>*>(this->mDat->data)->data();
		}
		template<typename T> const T& val(bool raw=false) const
		{
			if(typeid(T)!=this->type())
				throw cov::error("E0006");
			if(this->mDat==nullptr)
				throw cov::error("E0005");
			return dynamic_cast<const holder<T>*>(this->mDat->data)->data();
		}
		template<typename T> const T& const_val() const
		{
			if(typeid(T)!=this->type())
				throw cov::error("E0006");
			if(this->mDat==nullptr)
				throw cov::error("E0005");
			return dynamic_cast<const holder<T>*>(this->mDat->data)->data();
		}
		template<typename T> operator const T&() const
		{
			return this->const_val<T>();
		}
		void assign(const any& obj,bool raw=false)
		{
			if(&obj!=this&&obj.mDat!=mDat) {
				if(mDat!=nullptr&&obj.mDat!=nullptr&&raw) {
					delete mDat->data;
					mDat->data=obj.mDat->data->duplicate();
				} else {
					recycle();
					if(obj.mDat!=nullptr)
						mDat=new proxy(1,obj.mDat->data->duplicate());
					else
						mDat=nullptr;
				}
			}
		}
		template<typename T> void assign(const T& dat,bool raw=false)
		{
			if(raw) {
				delete mDat->data;
				mDat->data=new holder<T>(dat);
			} else {
				recycle();
				mDat=new proxy(1,new holder<T>(dat));
			}
		}
		template<typename T> any & operator=(const T& dat)
		{
			assign(dat);
			return *this;
		}
	};
	template<int N> class any::holder<char[N]>:public any::holder<std::string> {
	public:
		using holder<std::string>::holder;
	};
	template<> class any::holder<std::type_info>:public any::holder<std::type_index> {
	public:
		using holder<std::type_index>::holder;
	};
}

std::ostream& operator<<(std::ostream& out,const cov::any& val)
{
	out<<val.to_string();
	return out;
}

namespace std {
	template<> struct hash<cov::any> {
		std::size_t operator()(const cov::any& val) const
		{
			return val.hash();
		}
	};
}
<|endoftext|>


<commit_before>
#include "BaseExprHandler.h"

namespace typegrind {
BaseExprHandler::BaseExprHandler(clang::Rewriter*& rewriter,
                                 SpecializationHandler& specializationHandler)
    : mRewriter(rewriter), mSpecializationHandler(specializationHandler) {}

clang::StringRef BaseExprHandler::getID() const { return "typegrind"; }

bool BaseExprHandler::processingLocation(clang::SourceLocation loc) {
  if (mAlreadyProcessed.find(loc.getRawEncoding()) != mAlreadyProcessed.end()) return false;
  mAlreadyProcessed.insert(loc.getRawEncoding());
  return true;
}

bool BaseExprHandler::isReallyDependentType(
    clang::QualType const& typeInfo, PointeeConversion convertToPointee /*=KEEP_ORIGINAL_TYPE*/) {
  clang::LangOptions options;
  clang::PrintingPolicy policy(options);
  policy.SuppressUnwrittenScope = true;
  policy.SuppressTagKeyword = true;

  clang::QualType baseType = typeInfo;
  if (convertToPointee == CONVERT_TO_POINTEE && !baseType->getPointeeType().isNull()) {
    baseType = baseType->getPointeeType();
  }
  // TODO: better!
  std::string name = baseType.getAsString(policy);
  return name == "<dependent-type>";
}

void BaseExprHandler::addTypeInformationParameters(
    MacroAdder& macroAdder, clang::QualType const& typeInfo, unsigned specificUniqId,
    PointeeConversion convertToPointee /*=KEEP_ORIGINAL_TYPE*/) {
  clang::LangOptions options;
  clang::PrintingPolicy policy(options);
  policy.SuppressUnwrittenScope = true;
  policy.SuppressTagKeyword = true;

  if (typeInfo.getTypePtr()->isInstantiationDependentType()) {
    clang::QualType baseType = typeInfo;
    if (convertToPointee == CONVERT_TO_POINTEE && !baseType->getPointeeType().isNull()) {
      baseType = baseType->getPointeeType();
    }
    macroAdder.addParameter("TYPEGRIND_CANONICAL_TYPE(TYPEGRIND_TYPE(" +
                            baseType.getAsString(policy) + "))");
    macroAdder.addParameter("TYPEGRIND_SPECIFIC_TYPE(TYPEGRIND_TYPE(" +
                            baseType.getAsString(policy) + "), " + std::to_string(specificUniqId) +
                            ")");
  } else {
    clang::QualType baseType = typeInfo;
    if (convertToPointee == CONVERT_TO_POINTEE && !baseType->getPointeeType().isNull()) {
      baseType = baseType->getPointeeType();
    }
    macroAdder.addParameterAsString(baseType.getAsString());
    clang::QualType qt = typeInfo;
    if (!qt.isCanonical()) qt = qt.getCanonicalType();
    if (convertToPointee == CONVERT_TO_POINTEE && !qt->getPointeeType().isNull()) {
      qt = qt->getPointeeType();
    }
    macroAdder.addParameterAsString(qt.getAsString());
  }
}

void BaseExprHandler::handleSpecializedType(
    clang::QualType const& typeInfo, unsigned specificUniqId,
    PointeeConversion convertToPointee /*=KEEP_ORIGINAL_TYPE*/) {
  mSpecializationHandler.handleSpecializedType(typeInfo, specificUniqId, convertToPointee);
}

void BaseExprHandler::addSizeOfParameter(MacroAdder& macroAdder, clang::QualType const& typeInfo) {
  clang::LangOptions options;
  clang::PrintingPolicy policy(options);
  policy.SuppressUnwrittenScope = true;
  policy.SuppressTagKeyword = true;
  macroAdder.endBuffer() << ", sizeof(" << typeInfo.getAsString(policy) << ")";
}
}
<commit_msg>fixed typo in dependent type<commit_after>
#include "BaseExprHandler.h"

namespace typegrind {
BaseExprHandler::BaseExprHandler(clang::Rewriter*& rewriter,
                                 SpecializationHandler& specializationHandler)
    : mRewriter(rewriter), mSpecializationHandler(specializationHandler) {}

clang::StringRef BaseExprHandler::getID() const { return "typegrind"; }

bool BaseExprHandler::processingLocation(clang::SourceLocation loc) {
  if (mAlreadyProcessed.find(loc.getRawEncoding()) != mAlreadyProcessed.end()) return false;
  mAlreadyProcessed.insert(loc.getRawEncoding());
  return true;
}

bool BaseExprHandler::isReallyDependentType(
    clang::QualType const& typeInfo, PointeeConversion convertToPointee /*=KEEP_ORIGINAL_TYPE*/) {
  clang::LangOptions options;
  clang::PrintingPolicy policy(options);
  policy.SuppressUnwrittenScope = true;
  policy.SuppressTagKeyword = true;

  clang::QualType baseType = typeInfo;
  if (convertToPointee == CONVERT_TO_POINTEE && !baseType->getPointeeType().isNull()) {
    baseType = baseType->getPointeeType();
  }
  // TODO: better!
  std::string name = baseType.getAsString(policy);
  return name == "<dependent type>";
}

void BaseExprHandler::addTypeInformationParameters(
    MacroAdder& macroAdder, clang::QualType const& typeInfo, unsigned specificUniqId,
    PointeeConversion convertToPointee /*=KEEP_ORIGINAL_TYPE*/) {
  clang::LangOptions options;
  clang::PrintingPolicy policy(options);
  policy.SuppressUnwrittenScope = true;
  policy.SuppressTagKeyword = true;

  if (typeInfo.getTypePtr()->isInstantiationDependentType()) {
    clang::QualType baseType = typeInfo;
    if (convertToPointee == CONVERT_TO_POINTEE && !baseType->getPointeeType().isNull()) {
      baseType = baseType->getPointeeType();
    }
    macroAdder.addParameter("TYPEGRIND_CANONICAL_TYPE(TYPEGRIND_TYPE(" +
                            baseType.getAsString(policy) + "))");
    macroAdder.addParameter("TYPEGRIND_SPECIFIC_TYPE(TYPEGRIND_TYPE(" +
                            baseType.getAsString(policy) + "), " + std::to_string(specificUniqId) +
                            ")");
  } else {
    clang::QualType baseType = typeInfo;
    if (convertToPointee == CONVERT_TO_POINTEE && !baseType->getPointeeType().isNull()) {
      baseType = baseType->getPointeeType();
    }
    macroAdder.addParameterAsString(baseType.getAsString());
    clang::QualType qt = typeInfo;
    if (!qt.isCanonical()) qt = qt.getCanonicalType();
    if (convertToPointee == CONVERT_TO_POINTEE && !qt->getPointeeType().isNull()) {
      qt = qt->getPointeeType();
    }
    macroAdder.addParameterAsString(qt.getAsString());
  }
}

void BaseExprHandler::handleSpecializedType(
    clang::QualType const& typeInfo, unsigned specificUniqId,
    PointeeConversion convertToPointee /*=KEEP_ORIGINAL_TYPE*/) {
  mSpecializationHandler.handleSpecializedType(typeInfo, specificUniqId, convertToPointee);
}

void BaseExprHandler::addSizeOfParameter(MacroAdder& macroAdder, clang::QualType const& typeInfo) {
  clang::LangOptions options;
  clang::PrintingPolicy policy(options);
  policy.SuppressUnwrittenScope = true;
  policy.SuppressTagKeyword = true;
  macroAdder.endBuffer() << ", sizeof(" << typeInfo.getAsString(policy) << ")";
}
}
<|endoftext|>


<commit_before>// @(#)root/base:$Name:  $:$Id: TViewer3DPad.cxx,v 1.4 2005/03/11 17:22:21 brun Exp $
// Author: Richard Maunder  10/3/2005

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TViewer3DPad.h"
#include "TVirtualPad.h"
#include "TView.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"

#include <assert.h>

//______________________________________________________________________________
Bool_t TViewer3DPad::PreferLocalFrame() const
{
   // Indicates if we prefer positions in local frame. Always false - pad
   // drawing is always done in master frame.
   return kFALSE;
}

//______________________________________________________________________________
void TViewer3DPad::BeginScene()
{
   // Open a scene on the viewer. Is re-entrant as pad requires a two pass
   // draw.
   assert(!fBuilding);

   // Create a 3D view if none exists
   TView *view = fPad.GetView();
   if (!view) {
      view = new TView(11); // Perspective view by default
      if (!view) {
         assert(kFALSE);
         return;
      }
      fPad.SetView(view);
   }

   // Perform a first pass to calculate the range
   if (!fBuilding && !view->GetAutoRange()) {
      view->SetAutoRange(kTRUE);
   }
   fBuilding = kTRUE;
}

//______________________________________________________________________________
void TViewer3DPad::EndScene()
{
   // Close the scene on the viewer
   assert(fBuilding);

   // If we are doing for auto-range pass on view invoke another pass
   TView *view = fPad.GetView();
   if (view) {
      if (view->GetAutoRange()) {
         view->SetAutoRange(kFALSE);
         fPad.Paint();
      }
   }

   fBuilding = kFALSE;
}

//______________________________________________________________________________
Int_t TViewer3DPad::AddObject(const TBuffer3D & buffer, Bool_t * addChildren)
{
   // Add an 3D object described by the buffer to the viewer. Returns flags
   // to indicate:
   // i) if extra sections of the buffer need completing.
   // ii) if child objects of the buffer object should be added (always true)

   // Accept any children
   if (addChildren) {
      *addChildren = kTRUE;
   }

   TView * view = fPad.GetView();
   if (!view) {
      assert(kFALSE);
      return TBuffer3D::kNone;
   }

   UInt_t reqSections = TBuffer3D::kCore|TBuffer3D::kRawSizes|TBuffer3D::kRaw;
   if (!buffer.SectionsValid(reqSections)) {
      return reqSections;
   }

   UInt_t i;
   Int_t i0, i1, i2;

   // Range pass
   if (view->GetAutoRange()) {
      Double_t x0, y0, z0, x1, y1, z1;

      x0 = x1 = buffer.fPnts[0];
      y0 = y1 = buffer.fPnts[1];
      z0 = z1 = buffer.fPnts[2];
      for (i=1; i<buffer.NbPnts(); i++) {
         i0 = 3*i; i1 = i0+1; i2 = i0+2;
         x0 = buffer.fPnts[i0] < x0 ? buffer.fPnts[i0] : x0;
         y0 = buffer.fPnts[i1] < y0 ? buffer.fPnts[i1] : y0;
         z0 = buffer.fPnts[i2] < z0 ? buffer.fPnts[i2] : z0;
         x1 = buffer.fPnts[i0] > x1 ? buffer.fPnts[i0] : x1;
         y1 = buffer.fPnts[i1] > y1 ? buffer.fPnts[i1] : y1;
         z1 = buffer.fPnts[i2] > z1 ? buffer.fPnts[i2] : z1;
      }
      view->SetRange(x0,y0,z0,x1,y1,z1,2);
   }
   // Actual drawing pass
   else {
      // Do not show semi transparent objects
      if (buffer.fTransparency > 50) {
         return TBuffer3D::kNone;
      }
      if (buffer.Type()== TBuffer3DTypes::kMarker ) {
         Double_t pndc[3], temp[3];
         for (i=0; i<buffer.NbPnts(); i++) {
            for ( i0=0; i0<3; i0++ ) temp[i0] = buffer.fPnts[3*i+i0];
            view->WCtoNDC(temp, pndc);
            fPad.PaintPolyMarker(1, &pndc[0], &pndc[1]);
         }
      } else {
         for (i=0; i<buffer.NbSegs(); i++) {
            i0 = 3*buffer.fSegs[3*i+1];
            Double_t *ptpoints_0 = &(buffer.fPnts[i0]);
            i0 = 3*buffer.fSegs[3*i+2];
            Double_t *ptpoints_3 = &(buffer.fPnts[i0]);
            fPad.PaintLine3D(ptpoints_0, ptpoints_3);
         }
      }
   }

   return TBuffer3D::kNone;
}

//______________________________________________________________________________
Int_t TViewer3DPad::AddObject(UInt_t /*placedID*/, const TBuffer3D & buffer, Bool_t * addChildren)
{
   // We don't support placed ID shapes - ID is discarded
   return AddObject(buffer,addChildren);
}
<commit_msg>From Richard:  - modified TView to be perspective by default. Revert to cartesian as in v1.3<commit_after>// @(#)root/base:$Name:  $:$Id: TViewer3DPad.cxx,v 1.5 2005/03/18 08:03:27 brun Exp $
// Author: Richard Maunder  10/3/2005

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TViewer3DPad.h"
#include "TVirtualPad.h"
#include "TView.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"

#include <assert.h>

//______________________________________________________________________________
Bool_t TViewer3DPad::PreferLocalFrame() const
{
   // Indicates if we prefer positions in local frame. Always false - pad
   // drawing is always done in master frame.
   return kFALSE;
}

//______________________________________________________________________________
void TViewer3DPad::BeginScene()
{
   // Open a scene on the viewer. Is re-entrant as pad requires a two pass
   // draw.
   assert(!fBuilding);

   // Create a 3D view if none exists
   TView *view = fPad.GetView();
   if (!view) {
      view = new TView(1); // Cartesian view by default
      if (!view) {
         assert(kFALSE);
         return;
      }
      fPad.SetView(view);
   }

   // Perform a first pass to calculate the range
   if (!fBuilding && !view->GetAutoRange()) {
      view->SetAutoRange(kTRUE);
   }
   fBuilding = kTRUE;
}

//______________________________________________________________________________
void TViewer3DPad::EndScene()
{
   // Close the scene on the viewer
   assert(fBuilding);

   // If we are doing for auto-range pass on view invoke another pass
   TView *view = fPad.GetView();
   if (view) {
      if (view->GetAutoRange()) {
         view->SetAutoRange(kFALSE);
         fPad.Paint();
      }
   }

   fBuilding = kFALSE;
}

//______________________________________________________________________________
Int_t TViewer3DPad::AddObject(const TBuffer3D & buffer, Bool_t * addChildren)
{
   // Add an 3D object described by the buffer to the viewer. Returns flags
   // to indicate:
   // i) if extra sections of the buffer need completing.
   // ii) if child objects of the buffer object should be added (always true)

   // Accept any children
   if (addChildren) {
      *addChildren = kTRUE;
   }

   TView * view = fPad.GetView();
   if (!view) {
      assert(kFALSE);
      return TBuffer3D::kNone;
   }

   UInt_t reqSections = TBuffer3D::kCore|TBuffer3D::kRawSizes|TBuffer3D::kRaw;
   if (!buffer.SectionsValid(reqSections)) {
      return reqSections;
   }

   UInt_t i;
   Int_t i0, i1, i2;

   // Range pass
   if (view->GetAutoRange()) {
      Double_t x0, y0, z0, x1, y1, z1;

      x0 = x1 = buffer.fPnts[0];
      y0 = y1 = buffer.fPnts[1];
      z0 = z1 = buffer.fPnts[2];
      for (i=1; i<buffer.NbPnts(); i++) {
         i0 = 3*i; i1 = i0+1; i2 = i0+2;
         x0 = buffer.fPnts[i0] < x0 ? buffer.fPnts[i0] : x0;
         y0 = buffer.fPnts[i1] < y0 ? buffer.fPnts[i1] : y0;
         z0 = buffer.fPnts[i2] < z0 ? buffer.fPnts[i2] : z0;
         x1 = buffer.fPnts[i0] > x1 ? buffer.fPnts[i0] : x1;
         y1 = buffer.fPnts[i1] > y1 ? buffer.fPnts[i1] : y1;
         z1 = buffer.fPnts[i2] > z1 ? buffer.fPnts[i2] : z1;
      }
      view->SetRange(x0,y0,z0,x1,y1,z1,2);
   }
   // Actual drawing pass
   else {
      // Do not show semi transparent objects
      if (buffer.fTransparency > 50) {
         return TBuffer3D::kNone;
      }
      if (buffer.Type()== TBuffer3DTypes::kMarker ) {
         Double_t pndc[3], temp[3];
         for (i=0; i<buffer.NbPnts(); i++) {
            for ( i0=0; i0<3; i0++ ) temp[i0] = buffer.fPnts[3*i+i0];
            view->WCtoNDC(temp, pndc);
            fPad.PaintPolyMarker(1, &pndc[0], &pndc[1]);
         }
      } else {
         for (i=0; i<buffer.NbSegs(); i++) {
            i0 = 3*buffer.fSegs[3*i+1];
            Double_t *ptpoints_0 = &(buffer.fPnts[i0]);
            i0 = 3*buffer.fSegs[3*i+2];
            Double_t *ptpoints_3 = &(buffer.fPnts[i0]);
            fPad.PaintLine3D(ptpoints_0, ptpoints_3);
         }
      }
   }

   return TBuffer3D::kNone;
}

//______________________________________________________________________________
Int_t TViewer3DPad::AddObject(UInt_t /*placedID*/, const TBuffer3D & buffer, Bool_t * addChildren)
{
   // We don't support placed ID shapes - ID is discarded
   return AddObject(buffer,addChildren);
}
<|endoftext|>


<commit_before>/// @file
/// @version 1.0
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <theoraplayer/Manager.h>
#include <theoraplayer/theoraplayer.h>

#include "clipavfoundation.h"
#include "VideoClip.h"

namespace clipavfoundation
{
	static bool initialized = false;

	void init()
	{
#ifdef __APPLE__
		theoraplayer::log("Initializing AVFoundation VideoClip support for Theoraplayer.");
		theoraplayer::VideoClip::Format format;
		format.name = FORMAT_NAME;
		format.extension = ".mp4";
		format.createFunction = &clipavfoundation::VideoClip::create;
		theoraplayer::registerVideoClipFormat(format);
#else
		theoraplayer::log("AVFoundation VideoClip is not support on non-Apple OSes.");
#endif
	}

	void destroy()
	{
#ifdef __APPLE__
		theoraplayer::log("Destroying AVFoundation VideoClip for Theoraplayer.");
		theoraplayer::unregisterVideoClipFormat(FORMAT_NAME);
#endif
	}

}
<commit_msg>commented out unused variable<commit_after>/// @file
/// @version 1.0
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <theoraplayer/Manager.h>
#include <theoraplayer/theoraplayer.h>

#include "clipavfoundation.h"
#include "VideoClip.h"

namespace clipavfoundation
{
//	static bool initialized = false;

	void init()
	{
#ifdef __APPLE__
		theoraplayer::log("Initializing AVFoundation VideoClip support for Theoraplayer.");
		theoraplayer::VideoClip::Format format;
		format.name = FORMAT_NAME;
		format.extension = ".mp4";
		format.createFunction = &clipavfoundation::VideoClip::create;
		theoraplayer::registerVideoClipFormat(format);
#else
		theoraplayer::log("AVFoundation VideoClip is not support on non-Apple OSes.");
#endif
	}

	void destroy()
	{
#ifdef __APPLE__
		theoraplayer::log("Destroying AVFoundation VideoClip for Theoraplayer.");
		theoraplayer::unregisterVideoClipFormat(FORMAT_NAME);
#endif
	}

}
<|endoftext|>


<commit_before>#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "persistenceDiagrams/IO.hh"
#include "persistenceDiagrams/PersistenceDiagram.hh"
#include "persistenceDiagrams/PersistenceIndicatorFunction.hh"

using DataType           = double;
using PersistenceDiagram = aleph::PersistenceDiagram<DataType>;
using StepFunction       = aleph::math::StepFunction<double>;

template <class Map> void print( std::ostream& o, const Map& m )
{
  for( auto it = m.begin(); it != m.end(); ++it )
  {
    if( it != m.begin() )
      o << "\t";

    o << *it;
  }

  o << "\n";
}

int main( int argc, char** argv )
{
  if( argc <= 3 )
  {
    // TODO: Show usage
    return -1;
  }

  unsigned n = static_cast<unsigned>( std::stoul( argv[1] ) );

  std::vector<std::string> filenames;
  std::vector<PersistenceDiagram> persistenceDiagrams;
  std::vector<StepFunction> persistenceIndicatorFunctions;

  std::set<DataType> domain;

  for( int i = 2; i < argc; i++ )
  {
    filenames.push_back( argv[i] );

    std::cerr << "* Processing '" << argv[i] << "'...";

    PersistenceDiagram persistenceDiagram
        = aleph::load<DataType>( filenames.back() );

    persistenceDiagram.removeDiagonal();
    persistenceDiagram.removeUnpaired();

    persistenceDiagrams.push_back( persistenceDiagram );
    persistenceIndicatorFunctions.push_back( aleph::persistenceIndicatorFunction( persistenceDiagram ) );

    persistenceIndicatorFunctions.back().domain(
      std::inserter( domain, domain.begin() ) );

    std::cerr << "finished\n";
  }

  if( domain.empty() )
    return -1;

  auto min = *domain.begin();
  auto max = *domain.rbegin();

  std::cerr << "* Domain: [" << min << "," << max << "]\n";

  // Prepare bins ------------------------------------------------------

  std::vector<DataType> linbins;
  std::vector<DataType> logbins;

  linbins.reserve( n );
  logbins.reserve( n );

  for( unsigned i = 0; i < n; i++ )
  {
    auto offset = ( max - min ) / (n-1);
    auto value  = min + i * offset;

    linbins.push_back( value );
  }

  std::cerr << "* Linear-spaced bins: ";

  for( auto&& linbin : linbins )
    std::cerr << linbin << " ";

  std::cerr << "\n";

  for( unsigned i = 0; i < n; i++ )
  {
    auto offset = ( std::log10( max ) - std::log10( min ) ) / (n-1);
    auto value  = std::log10( min ) + i * offset;

    logbins.push_back( value );
  }

  std::transform( logbins.begin(), logbins.end(),
                  logbins.begin(),
                  [] ( const DataType x )
                  {
                    return std::pow( DataType(10), x );
                  } );

  std::cerr << "* Log-spaced bins: ";

  for( auto&& logbin : logbins )
    std::cerr << logbin << " ";

  std::cerr << "\n";

  // Prepare histogram calculation -------------------------------------

  auto valueToLinIndex = [&min, &max, &linbins, &n] ( DataType value )
  {
    auto offset = ( max - min ) / (n-1);
    return static_cast<std::size_t>( ( value - min ) / offset );
  };

  auto valueToLogIndex = [&min, &max, &logbins, &n] ( DataType value )
  {
    auto offset = ( std::log10( max ) - std::log10( min ) ) / (n-1);
    return static_cast<std::size_t>( ( std::log10( value ) - std::log10( min ) ) / offset );
  };

  std::ofstream linout( "/tmp/DNA_" + std::to_string( n ) + "_lin.txt" );
  std::ofstream logout( "/tmp/DNA_" + std::to_string( n ) + "_log.txt" );

  auto makeHeader = [] ( std::ofstream& out, const std::vector<DataType>& bins )
  {
    unsigned index = 0;
    out << "unset border\n";
    out << "set key off\n";
    out << "set xtics (";

    for( auto&& bin : bins )
    {
      if( index != 0 )
        out << ",";

      out << "\"" << bin <<  "\" " << index;

      ++index;
    }

    out << ") nomirror\n";

    out << "plot '-' matrix with image\n";
  };

  makeHeader( linout, linbins );
  makeHeader( logout, logbins );

  for( auto&& pif : persistenceIndicatorFunctions )
  {
    std::vector<DataType> linhist(n);
    std::vector<DataType> loghist(n);

    std::set<DataType> domain;
    pif.domain( std::inserter( domain, domain.begin() ) );

    for( auto&& x : domain )
    {
      auto value  = pif(x);
      auto linbin = valueToLinIndex(x);
      auto logbin = valueToLogIndex(x);

      linhist.at(linbin) += value;

      if( logbin < loghist.size() )
        loghist.at(logbin) += value;
    }

    print( linout, linhist );
    print( logout, loghist );
  }

  logout << "e\n";
}
<commit_msg>Updated & simplified clique DNA output<commit_after>#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "persistenceDiagrams/IO.hh"
#include "persistenceDiagrams/PersistenceDiagram.hh"
#include "persistenceDiagrams/PersistenceIndicatorFunction.hh"

using DataType           = double;
using PersistenceDiagram = aleph::PersistenceDiagram<DataType>;
using StepFunction       = aleph::math::StepFunction<double>;

/*
  Prints a vector in a simple matrix-like format. Given a row index, all
  of the entries are considered to be the columns of the matrix:

    Input:   {4,5,6}, row = 23

    Output:  23 0 4
             23 1 5
             23 2 6
             <empty line>

  This output format is flexible and permits direct usage in other tools
  such as TikZ or pgfplots.
*/

template <class Map> void print( std::ostream& o, const Map& m, unsigned row )
{
  unsigned column = 0;
  for( auto it = m.begin(); it != m.end(); ++it )
    o << row << "\t" << column++ << "\t" << *it << "\n";

  o << "\n";
}

int main( int argc, char** argv )
{
  if( argc <= 3 )
  {
    // TODO: Show usage
    return -1;
  }

  unsigned n = static_cast<unsigned>( std::stoul( argv[1] ) );

  std::vector<std::string> filenames;
  std::vector<PersistenceDiagram> persistenceDiagrams;
  std::vector<StepFunction> persistenceIndicatorFunctions;

  std::set<DataType> domain;

  for( int i = 2; i < argc; i++ )
  {
    filenames.push_back( argv[i] );

    std::cerr << "* Processing '" << argv[i] << "'...";

    PersistenceDiagram persistenceDiagram
        = aleph::load<DataType>( filenames.back() );

    persistenceDiagram.removeDiagonal();
    persistenceDiagram.removeUnpaired();

    persistenceDiagrams.push_back( persistenceDiagram );
    persistenceIndicatorFunctions.push_back( aleph::persistenceIndicatorFunction( persistenceDiagram ) );

    persistenceIndicatorFunctions.back().domain(
      std::inserter( domain, domain.begin() ) );

    std::cerr << "finished\n";
  }

  if( domain.empty() )
    return -1;

  auto min = *domain.begin();
  auto max = *domain.rbegin();

  std::cerr << "* Domain: [" << min << "," << max << "]\n";

  // Prepare bins ------------------------------------------------------

  std::vector<DataType> linbins;
  std::vector<DataType> logbins;

  linbins.reserve( n );
  logbins.reserve( n );

  for( unsigned i = 0; i < n; i++ )
  {
    auto offset = ( max - min ) / (n-1);
    auto value  = min + i * offset;

    linbins.push_back( value );
  }

  std::cerr << "* Linear-spaced bins: ";

  for( auto&& linbin : linbins )
    std::cerr << linbin << " ";

  std::cerr << "\n";

  for( unsigned i = 0; i < n; i++ )
  {
    auto offset = ( std::log10( max ) - std::log10( min ) ) / (n-1);
    auto value  = std::log10( min ) + i * offset;

    logbins.push_back( value );
  }

  std::transform( logbins.begin(), logbins.end(),
                  logbins.begin(),
                  [] ( const DataType x )
                  {
                    return std::pow( DataType(10), x );
                  } );

  std::cerr << "* Log-spaced bins: ";

  for( auto&& logbin : logbins )
    std::cerr << logbin << " ";

  std::cerr << "\n";

  // Prepare histogram calculation -------------------------------------

  auto valueToLinIndex = [&min, &max, &linbins, &n] ( DataType value )
  {
    auto offset = ( max - min ) / (n-1);
    return static_cast<std::size_t>( ( value - min ) / offset );
  };

  auto valueToLogIndex = [&min, &max, &logbins, &n] ( DataType value )
  {
    auto offset = ( std::log10( max ) - std::log10( min ) ) / (n-1);
    return static_cast<std::size_t>( ( std::log10( value ) - std::log10( min ) ) / offset );
  };

  std::ofstream linout( "/tmp/DNA_" + std::to_string( n ) + "_lin.txt" );
  std::ofstream logout( "/tmp/DNA_" + std::to_string( n ) + "_log.txt" );

  unsigned index = 0;
  for( auto&& pif : persistenceIndicatorFunctions )
  {
    std::vector<DataType> linhist(n);
    std::vector<DataType> loghist(n);

    std::set<DataType> domain;
    pif.domain( std::inserter( domain, domain.begin() ) );

    for( auto&& x : domain )
    {
      auto value  = pif(x);
      auto linbin = valueToLinIndex(x);
      auto logbin = valueToLogIndex(x);

      linhist.at(linbin) += value;

      if( logbin < loghist.size() )
        loghist.at(logbin) += value;
    }

    print( linout, linhist, index );
    print( logout, loghist, index );

    ++index;
  }
}
<|endoftext|>


<commit_before><commit_msg>ignore audio error and play video without audio BUG=16023 TEST=play a multichannel audio video and it should play with audio muted Review URL: http://codereview.chromium.org/155937<commit_after><|endoftext|>


<commit_before>// $Id$
// (c) Wolfgang Bangerth
//
// Show the shape functions of the Nedelec element on a grid with
// only one cell. This cell is rotated, stretched, scaled, etc, and
// each time we evaluate the shape functions.

#include <base/quadrature_lib.h>
#include <base/logstream.h>
#include <lac/vector.h>
#include <grid/tria.h>
#include <grid/tria_iterator.h>
#include <dofs/dof_accessor.h>
#include <grid/grid_generator.h>
#include <grid/grid_tools.h>
#include <fe/fe_nedelec.h>
#include <fe/fe_values.h>

#include <vector>
#include <fstream>
#include <string>

#define PRECISION 2

Point<2> stretch_coordinates (const Point<2> p)
{
  return Point<2>(2*p(0), p(1));
}

Point<2> tilt_coordinates (const Point<2> p)
{
  return Point<2>(p(0)+p(1), p(1));
}

void
transform_grid (Triangulation<2> &tria,
		const unsigned int  transform)
{
  switch (transform)
    {
                                       // first round: take
                                       // original grid
      case 0:
	    break;

					     // second round: rotate
					     // triangulation
      case 1:
	    GridTools::rotate (3.14159265358/2, tria);
	    break;

					     // third round: inflate
					     // by a factor of 2
      case 2:
	    GridTools::scale (2, tria);
	    break;

                                             // third round: scale
                                             // back, rotate back,
                                             // stretch
      case 3:
            GridTools::scale (.5, tria);
	    GridTools::rotate (-3.14159265358/2, tria);
            GridTools::transform (&stretch_coordinates, tria);

	    break;

      default:
	    Assert (false, ExcNotImplemented());
    };
}

template<int dim>
inline void
plot_shape_functions()
{
  FE_Nedelec<dim> fe_ned(1);
  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr, 0., 1.);

				   // check the following with a
				   // number of transformed
				   // triangulations
  for (unsigned int transform=0; transform<4; ++transform)
    {
      deallog << "GRID TRANSFORMATION " << transform << std::endl;

      transform_grid (tr, transform);

      DoFHandler<dim> dof(tr);
      typename DoFHandler<dim>::cell_iterator c = dof.begin();
      dof.distribute_dofs(fe_ned);

      QTrapez<1> q_trapez;
      const unsigned int div=2;
      QIterated<dim> q(q_trapez, div);
      FEValues<dim> fe(fe_ned, q, update_values|update_gradients|update_q_points);
      fe.reinit(c);

      unsigned int q_point=0;
      for (unsigned int mz=0;mz<=((dim>2) ? div : 0) ;++mz)
	for (unsigned int my=0;my<=((dim>1) ? div : 0) ;++my)
	  for (unsigned int mx=0;mx<=div;++mx)
	    {
	      deallog << "q_point(" << q_point << ")=" << fe.quadrature_point(q_point)
		      << std::endl;

	      for (unsigned int i=0;i<fe_ned.dofs_per_cell;++i)
		{
		  deallog << "  phi(" << i << ") = [";
		  for (unsigned int c=0; c<fe.get_fe().n_components(); ++c)
		    deallog << " " << fe.shape_value_component(i,q_point,c);
		  deallog << " ]" << std::endl;
		};
	      for (unsigned int i=0;i<fe_ned.dofs_per_cell;++i)
		{
		  deallog << "  grad phi(" << i << ") = ";
		  for (unsigned int c=0; c<dim; ++c)
                    {
                      deallog << "[";
                      for (unsigned int d=0; d<dim; ++d)
                        deallog << " " << fe.shape_grad_component(i,q_point,c)[d];
                      deallog << " ]" << std::endl;
                      if (c != dim-1)
                        deallog << "                ";
                    };
		};

              q_point++;
	    }

      deallog << std::endl;
    }
}

int
main()
{
  std::ofstream logfile ("nedelec.output");
  logfile.precision (PRECISION);
  logfile.setf(std::ios::fixed);
  deallog.attach(logfile);
  deallog.depth_console(0);

  plot_shape_functions<2>();
//  plot_shape_functions<3>();

  return 0;
}

<commit_msg>Fix comment.<commit_after>// $Id$
// (c) Wolfgang Bangerth
//
// Show the shape functions of the Nedelec element on a grid with only
// one cell. This cell is rotated, stretched, scaled, etc, and on each
// of these cells each time we evaluate the shape functions.

#include <base/quadrature_lib.h>
#include <base/logstream.h>
#include <lac/vector.h>
#include <grid/tria.h>
#include <grid/tria_iterator.h>
#include <dofs/dof_accessor.h>
#include <grid/grid_generator.h>
#include <grid/grid_tools.h>
#include <fe/fe_nedelec.h>
#include <fe/fe_values.h>

#include <vector>
#include <fstream>
#include <string>

#define PRECISION 2

Point<2> stretch_coordinates (const Point<2> p)
{
  return Point<2>(2*p(0), p(1));
}

Point<2> tilt_coordinates (const Point<2> p)
{
  return Point<2>(p(0)+p(1), p(1));
}

void
transform_grid (Triangulation<2> &tria,
		const unsigned int  transform)
{
  switch (transform)
    {
                                       // first round: take
                                       // original grid
      case 0:
	    break;

					     // second round: rotate
					     // triangulation
      case 1:
	    GridTools::rotate (3.14159265358/2, tria);
	    break;

					     // third round: inflate
					     // by a factor of 2
      case 2:
	    GridTools::scale (2, tria);
	    break;

                                             // third round: scale
                                             // back, rotate back,
                                             // stretch
      case 3:
            GridTools::scale (.5, tria);
	    GridTools::rotate (-3.14159265358/2, tria);
            GridTools::transform (&stretch_coordinates, tria);

	    break;

      default:
	    Assert (false, ExcNotImplemented());
    };
}

template<int dim>
inline void
plot_shape_functions()
{
  FE_Nedelec<dim> fe_ned(1);
  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr, 0., 1.);

				   // check the following with a
				   // number of transformed
				   // triangulations
  for (unsigned int transform=0; transform<4; ++transform)
    {
      deallog << "GRID TRANSFORMATION " << transform << std::endl;

      transform_grid (tr, transform);

      DoFHandler<dim> dof(tr);
      typename DoFHandler<dim>::cell_iterator c = dof.begin();
      dof.distribute_dofs(fe_ned);

      QTrapez<1> q_trapez;
      const unsigned int div=2;
      QIterated<dim> q(q_trapez, div);
      FEValues<dim> fe(fe_ned, q, update_values|update_gradients|update_q_points);
      fe.reinit(c);

      unsigned int q_point=0;
      for (unsigned int mz=0;mz<=((dim>2) ? div : 0) ;++mz)
	for (unsigned int my=0;my<=((dim>1) ? div : 0) ;++my)
	  for (unsigned int mx=0;mx<=div;++mx)
	    {
	      deallog << "q_point(" << q_point << ")=" << fe.quadrature_point(q_point)
		      << std::endl;

	      for (unsigned int i=0;i<fe_ned.dofs_per_cell;++i)
		{
		  deallog << "  phi(" << i << ") = [";
		  for (unsigned int c=0; c<fe.get_fe().n_components(); ++c)
		    deallog << " " << fe.shape_value_component(i,q_point,c);
		  deallog << " ]" << std::endl;
		};
	      for (unsigned int i=0;i<fe_ned.dofs_per_cell;++i)
		{
		  deallog << "  grad phi(" << i << ") = ";
		  for (unsigned int c=0; c<dim; ++c)
                    {
                      deallog << "[";
                      for (unsigned int d=0; d<dim; ++d)
                        deallog << " " << fe.shape_grad_component(i,q_point,c)[d];
                      deallog << " ]" << std::endl;
                      if (c != dim-1)
                        deallog << "                ";
                    };
		};

              q_point++;
	    }

      deallog << std::endl;
    }
}

int
main()
{
  std::ofstream logfile ("nedelec.output");
  logfile.precision (PRECISION);
  logfile.setf(std::ios::fixed);
  deallog.attach(logfile);
  deallog.depth_console(0);

  plot_shape_functions<2>();
//  plot_shape_functions<3>();

  return 0;
}

<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/experimental/acceleration/mini_benchmark/runner.h"

// Implementation notes and rationale:
//
// This class's primary client is the mini-benchmark. The mini-benchmark tries
// out different acceleration configurations for TFLite. The acceleration may
// hang or crash due to driver bugs. Running in a separate process isolates the
// application from these hangs or crashes.
//
// The separate process is implemented in native code. The main alternative
// would be to use a separate service process at the Android application
// level. The most important drawbacks of that approach would have been
// manifest merge issues in tests (see for example b/158142805) and the need for
// all applications to explicitly integrate the mini-benchmark at the app level.
//
// The native code uses popen(3) for the separate process. This is one of the
// few officially supported ways of safely using fork(2) on Android (See
// b/129156634 for a discussion on popen use in Android studio device-side, see
// https://groups.google.com/g/android-platform/c/80jr-_A-9bU for discussion on
// fork in general).
//
// The native process executes a small helper binary that then dynamically
// loads the shared library that tflite code lives in. This allows for minimal
// code size as only one copy of the tflite code is needed.
//
// The 8kb helper binary is extracted into an app data folder On P- we execute
// it directly.  On Q+ this is no longer allowed (see b/112357170) but we can
// use /system/bin/linker(64) as a trampoline.  (See also Chrome's documentation
// for a similar problem:
// https://chromium.googlesource.com/chromium/src/+/master/docs/android_native_libraries.md#crashpad-packaging).
// Using /system/bin/linker(64) does not work before Android Q (See
// b/112050209).
//
// The shared library where the code to be called lives is a JNI library that
// contains tflite. We detect the path to that library with dladdr(3). This way
// differences in the way the JNI libraries are bundled, named or delivered is
// automatically handled. The downside is that dladdr is broken on Android 23
// for JNI libraries that are not extracted from the apk (See b/37069572). If
// this becomes a serious issue we can try to parse /proc/self/maps and the apk
// zip directory to figure out the name. The alternative where the caller needs
// to pass in the library name requires more integration work at the packaging
// (app or SDK) level.
//
// The methods in this class return detailed error codes, so that telemetry can
// be used to detect issues in production without using strings which can be
// hard to make privacy-compliant.

#ifdef __ANDROID__
#include <dlfcn.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifndef _WIN32
#include <unistd.h>
#endif

#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>

#include "tensorflow/lite/experimental/acceleration/compatibility/android_info.h"
#include "tensorflow/lite/experimental/acceleration/mini_benchmark/status_codes.h"
#ifdef __ANDROID__
#include "tensorflow/lite/experimental/acceleration/mini_benchmark/embedded_runner_executable.h"
#endif  // __ANDROID__

namespace tflite {
namespace acceleration {

namespace {
std::string ShellEscape(const std::string& src);
}

ProcessRunner::ProcessRunner(const std::string& temporary_path,
                             const std::string& function_name,
                             int (*function_pointer)(int argc, char** argv))
    : temporary_path_(temporary_path),
      function_name_(function_name),
      function_pointer_(reinterpret_cast<void*>(function_pointer)) {}

MinibenchmarkStatus ProcessRunner::Init() {
  if (!function_pointer_) {
    return kMinibenchmarkPreconditionNotMet;
  }
#ifndef __ANDROID__
  return kMinibenchmarkSuccess;
#else
  // Find name of this shared object.
  std::string soname;
  Dl_info dl_info;
  int status = dladdr(function_pointer_, &dl_info);
  if (status != 0) {
    if (dl_info.dli_fname) {
      soname = dl_info.dli_fname;
    } else {
      return kMinibenchmarkDliFnameWasNull;
    }
  } else {
    return kMinibenchmarkDladdrReturnedZero;
  }
  // Check for b/37069572 - on SDK level 23 dli_fname may not contain the
  // library name, only the apk. (See comment at top of file).
  if (soname.size() >= 4 && soname.substr(soname.size() - 4) == ".apk") {
    return kMinibenchmarkDliFnameHasApkNameOnly;
  }

  // Construct path to runner, extracting the helper binary if needed.
  std::string runner_path;
  // TODO(b/172541832): handle multiple concurrent callers.
  runner_path = temporary_path_ + "/runner";
  (void)unlink(runner_path.c_str());
  std::string runner_contents(
      reinterpret_cast<const char*>(g_tflite_acceleration_embedded_runner),
      g_tflite_acceleration_embedded_runner_len);
  std::ofstream f(runner_path, std::ios::binary);
  if (!f.is_open()) {
    return kMinibenchmarkCouldntOpenTemporaryFileForBinary;
  }
  f << runner_contents;
  f.close();
  if (chmod(runner_path.c_str(), 0500) != 0) {
    return kMinibenchmarkCouldntChmodTemporaryFile;
  }
  runner_path = ShellEscape(runner_path);
  tflite::acceleration::AndroidInfo android_info;
  if (!tflite::acceleration::RequestAndroidInfo(&android_info).ok()) {
    return kMinibenchmarkRequestAndroidInfoFailed;
  }
  if (android_info.android_sdk_version >= "29") {
    // On 29+ we need to use /system/bin/linker to load the binary from the app,
    // as exec()ing writable files was blocked for security. (See comment at top
    // of file).
#if defined(__arm__) || defined(__i386__)
    std::string linker_path = "/system/bin/linker";
#else
    std::string linker_path = "/system/bin/linker64";
#endif
    runner_path = linker_path + " " + runner_path;
  }

  // Commit.
  runner_path_ = runner_path;
  soname_ = soname;
  return kMinibenchmarkSuccess;
#endif  // !__ANDROID__
}

MinibenchmarkStatus ProcessRunner::Run(const std::vector<std::string>& args,
                                       std::string* output, int* exitcode,
                                       int* signal) {
#ifdef _WIN32
  return kMinibenchmarkUnsupportedPlatform;
#else  // !_WIN32
  if (!output || !exitcode) {
    return kMinibenchmarkPreconditionNotMet;
  }
  int benchmark_process_status = 0;
#ifndef __ANDROID__
  if (function_pointer_) {
    benchmark_process_status = RunInprocess(args);
  } else {
    return kMinibenchmarkPreconditionNotMet;
  }
#else
  if (runner_path_.empty()) {
    return kMinibenchmarkPreconditionNotMet;
  }
  // runner_path_ components are escaped earlier.
  std::string cmd = runner_path_ + " " + ShellEscape(soname_) + " " +
                    ShellEscape(function_name_);
  for (const auto& arg : args) {
    cmd = cmd + " " + ShellEscape(arg);
  }
  FILE* f = popen(cmd.c_str(), "r");
  if (!f) {
    *exitcode = errno;
    return kMinibenchmarkPopenFailed;
  }
  std::vector<char> buffer(4 * 1024, 0);
  ssize_t length;
  std::string ret;
  do {
    length = fread(buffer.data(), 1, buffer.size(), f);
    ret = ret + std::string(buffer.data(), length);
  } while (length == buffer.size());
  *output = ret;
  benchmark_process_status = pclose(f);
#endif  // !__ANDROID
  if (WIFEXITED(benchmark_process_status)) {
    *exitcode = WEXITSTATUS(benchmark_process_status);
    *signal = 0;
    if (*exitcode == kMinibenchmarkSuccess) {
      return kMinibenchmarkSuccess;
    }
  } else if (WIFSIGNALED(benchmark_process_status)) {
    *exitcode = 0;
    *signal = WTERMSIG(benchmark_process_status);
  }
  return kMinibenchmarkCommandFailed;
#endif  // _WIN32
}

#ifndef __ANDROID__

#ifndef __W_EXITCODE  // Mac
#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
#endif

int ProcessRunner::RunInprocess(const std::vector<std::string>& user_args) {
  int argc = user_args.size() + 3;
  std::vector<std::string> args(argc);
  args[0] = "inprocess";
  args[1] = "inprocess";
  args[2] = function_name_;
  for (int i = 0; i < user_args.size(); i++) {
    args[3 + i] = user_args[i];
  }
  std::vector<std::vector<char>> mutable_args(argc);
  std::vector<char*> argv(argc);
  for (int i = 0; i < mutable_args.size(); i++) {
    mutable_args[i] = {args[i].data(), args[i].data() + args[i].size()};
    mutable_args[i].push_back('\0');
    argv[i] = mutable_args[i].data();
  }
  int (*function_pointer)(int, char**) =
      reinterpret_cast<int (*)(int, char**)>(function_pointer_);
  return __W_EXITCODE(function_pointer(argc, argv.data()), 0);
}
#endif  // !__ANDROID__

namespace {

// kDontNeedShellEscapeChars and ShellEscape are copied from absl, which copied
// them from Python. Copied here because tflite core libraries should not depend
// on absl (both for size reasons and for possible version skew):

static const char kDontNeedShellEscapeChars[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+-_.=/:,@";

std::string ShellEscape(const std::string& src) {
  if (!src.empty() &&  // empty string needs quotes
      src.find_first_not_of(kDontNeedShellEscapeChars) == std::string::npos) {
    // only contains chars that don't need quotes; it's fine
    return src;
  } else if (src.find('\'') == std::string::npos) {  // NOLINT
    // no single quotes; just wrap it in single quotes
    return "'" + src + "'";
  } else {
    // needs double quote escaping
    std::string result = "\"";
    for (const char c : src) {
      switch (c) {
        case '\\':
        case '$':
        case '"':
        case '`':
          result.push_back('\\');
      }
      result.push_back(c);
    }
    result.push_back('"');
    return result;
  }
}
}  // namespace

}  // namespace acceleration
}  // namespace tflite
<commit_msg>Explicitly return an error from mini-benchmark on Android SDK versions < 23, which do not have acceleration and we don't test on.<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/experimental/acceleration/mini_benchmark/runner.h"

// Implementation notes and rationale:
//
// This class's primary client is the mini-benchmark. The mini-benchmark tries
// out different acceleration configurations for TFLite. The acceleration may
// hang or crash due to driver bugs. Running in a separate process isolates the
// application from these hangs or crashes.
//
// The separate process is implemented in native code. The main alternative
// would be to use a separate service process at the Android application
// level. The most important drawbacks of that approach would have been
// manifest merge issues in tests (see for example b/158142805) and the need for
// all applications to explicitly integrate the mini-benchmark at the app level.
//
// The native code uses popen(3) for the separate process. This is one of the
// few officially supported ways of safely using fork(2) on Android (See
// b/129156634 for a discussion on popen use in Android studio device-side, see
// https://groups.google.com/g/android-platform/c/80jr-_A-9bU for discussion on
// fork in general).
//
// The native process executes a small helper binary that then dynamically
// loads the shared library that tflite code lives in. This allows for minimal
// code size as only one copy of the tflite code is needed.
//
// The 8kb helper binary is extracted into an app data folder On P- we execute
// it directly.  On Q+ this is no longer allowed (see b/112357170) but we can
// use /system/bin/linker(64) as a trampoline.  (See also Chrome's documentation
// for a similar problem:
// https://chromium.googlesource.com/chromium/src/+/master/docs/android_native_libraries.md#crashpad-packaging).
// Using /system/bin/linker(64) does not work before Android Q (See
// b/112050209).
//
// The shared library where the code to be called lives is a JNI library that
// contains tflite. We detect the path to that library with dladdr(3). This way
// differences in the way the JNI libraries are bundled, named or delivered is
// automatically handled. The downside is that dladdr is broken on Android 23
// for JNI libraries that are not extracted from the apk (See b/37069572). If
// this becomes a serious issue we can try to parse /proc/self/maps and the apk
// zip directory to figure out the name. The alternative where the caller needs
// to pass in the library name requires more integration work at the packaging
// (app or SDK) level.
//
// The methods in this class return detailed error codes, so that telemetry can
// be used to detect issues in production without using strings which can be
// hard to make privacy-compliant.

#ifdef __ANDROID__
#include <dlfcn.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifndef _WIN32
#include <unistd.h>
#endif

#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>

#include "tensorflow/lite/experimental/acceleration/compatibility/android_info.h"
#include "tensorflow/lite/experimental/acceleration/mini_benchmark/status_codes.h"
#ifdef __ANDROID__
#include "tensorflow/lite/experimental/acceleration/mini_benchmark/embedded_runner_executable.h"
#endif  // __ANDROID__

namespace tflite {
namespace acceleration {

namespace {
std::string ShellEscape(const std::string& src);
}

ProcessRunner::ProcessRunner(const std::string& temporary_path,
                             const std::string& function_name,
                             int (*function_pointer)(int argc, char** argv))
    : temporary_path_(temporary_path),
      function_name_(function_name),
      function_pointer_(reinterpret_cast<void*>(function_pointer)) {}

MinibenchmarkStatus ProcessRunner::Init() {
  if (!function_pointer_) {
    return kMinibenchmarkPreconditionNotMet;
  }
#ifndef __ANDROID__
  return kMinibenchmarkSuccess;
#else
  tflite::acceleration::AndroidInfo android_info;
  if (!tflite::acceleration::RequestAndroidInfo(&android_info).ok()) {
    return kMinibenchmarkRequestAndroidInfoFailed;
  }
  if (android_info.android_sdk_version.length() < 2 ||
      android_info.android_sdk_version < "23") {
    // The codepaths have only been tested on 23+.
    return kMinibenchmarkUnsupportedPlatform;
  }

  // Find name of this shared object.
  std::string soname;
  Dl_info dl_info;
  int status = dladdr(function_pointer_, &dl_info);
  if (status != 0) {
    if (dl_info.dli_fname) {
      soname = dl_info.dli_fname;
    } else {
      return kMinibenchmarkDliFnameWasNull;
    }
  } else {
    return kMinibenchmarkDladdrReturnedZero;
  }
  // Check for b/37069572 - on SDK level 23 dli_fname may not contain the
  // library name, only the apk. (See comment at top of file).
  if (soname.size() >= 4 && soname.substr(soname.size() - 4) == ".apk") {
    return kMinibenchmarkDliFnameHasApkNameOnly;
  }

  // Construct path to runner, extracting the helper binary if needed.
  std::string runner_path;
  // TODO(b/172541832): handle multiple concurrent callers.
  runner_path = temporary_path_ + "/runner";
  (void)unlink(runner_path.c_str());
  std::string runner_contents(
      reinterpret_cast<const char*>(g_tflite_acceleration_embedded_runner),
      g_tflite_acceleration_embedded_runner_len);
  std::ofstream f(runner_path, std::ios::binary);
  if (!f.is_open()) {
    return kMinibenchmarkCouldntOpenTemporaryFileForBinary;
  }
  f << runner_contents;
  f.close();
  if (chmod(runner_path.c_str(), 0500) != 0) {
    return kMinibenchmarkCouldntChmodTemporaryFile;
  }
  runner_path = ShellEscape(runner_path);
  if (android_info.android_sdk_version >= "29") {
    // On 29+ we need to use /system/bin/linker to load the binary from the app,
    // as exec()ing writable files was blocked for security. (See comment at top
    // of file).
#if defined(__arm__) || defined(__i386__)
    std::string linker_path = "/system/bin/linker";
#else
    std::string linker_path = "/system/bin/linker64";
#endif
    runner_path = linker_path + " " + runner_path;
  }

  // Commit.
  runner_path_ = runner_path;
  soname_ = soname;
  return kMinibenchmarkSuccess;
#endif  // !__ANDROID__
}

MinibenchmarkStatus ProcessRunner::Run(const std::vector<std::string>& args,
                                       std::string* output, int* exitcode,
                                       int* signal) {
#ifdef _WIN32
  return kMinibenchmarkUnsupportedPlatform;
#else  // !_WIN32
  if (!output || !exitcode) {
    return kMinibenchmarkPreconditionNotMet;
  }
  int benchmark_process_status = 0;
#ifndef __ANDROID__
  if (function_pointer_) {
    benchmark_process_status = RunInprocess(args);
  } else {
    return kMinibenchmarkPreconditionNotMet;
  }
#else
  if (runner_path_.empty()) {
    return kMinibenchmarkPreconditionNotMet;
  }
  // runner_path_ components are escaped earlier.
  std::string cmd = runner_path_ + " " + ShellEscape(soname_) + " " +
                    ShellEscape(function_name_);
  for (const auto& arg : args) {
    cmd = cmd + " " + ShellEscape(arg);
  }
  FILE* f = popen(cmd.c_str(), "r");
  if (!f) {
    *exitcode = errno;
    return kMinibenchmarkPopenFailed;
  }
  std::vector<char> buffer(4 * 1024, 0);
  ssize_t length;
  std::string ret;
  do {
    length = fread(buffer.data(), 1, buffer.size(), f);
    ret = ret + std::string(buffer.data(), length);
  } while (length == buffer.size());
  *output = ret;
  benchmark_process_status = pclose(f);
#endif  // !__ANDROID
  if (WIFEXITED(benchmark_process_status)) {
    *exitcode = WEXITSTATUS(benchmark_process_status);
    *signal = 0;
    if (*exitcode == kMinibenchmarkSuccess) {
      return kMinibenchmarkSuccess;
    }
  } else if (WIFSIGNALED(benchmark_process_status)) {
    *exitcode = 0;
    *signal = WTERMSIG(benchmark_process_status);
  }
  return kMinibenchmarkCommandFailed;
#endif  // _WIN32
}

#ifndef __ANDROID__

#ifndef __W_EXITCODE  // Mac
#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
#endif

int ProcessRunner::RunInprocess(const std::vector<std::string>& user_args) {
  int argc = user_args.size() + 3;
  std::vector<std::string> args(argc);
  args[0] = "inprocess";
  args[1] = "inprocess";
  args[2] = function_name_;
  for (int i = 0; i < user_args.size(); i++) {
    args[3 + i] = user_args[i];
  }
  std::vector<std::vector<char>> mutable_args(argc);
  std::vector<char*> argv(argc);
  for (int i = 0; i < mutable_args.size(); i++) {
    mutable_args[i] = {args[i].data(), args[i].data() + args[i].size()};
    mutable_args[i].push_back('\0');
    argv[i] = mutable_args[i].data();
  }
  int (*function_pointer)(int, char**) =
      reinterpret_cast<int (*)(int, char**)>(function_pointer_);
  return __W_EXITCODE(function_pointer(argc, argv.data()), 0);
}
#endif  // !__ANDROID__

namespace {

// kDontNeedShellEscapeChars and ShellEscape are copied from absl, which copied
// them from Python. Copied here because tflite core libraries should not depend
// on absl (both for size reasons and for possible version skew):

static const char kDontNeedShellEscapeChars[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+-_.=/:,@";

std::string ShellEscape(const std::string& src) {
  if (!src.empty() &&  // empty string needs quotes
      src.find_first_not_of(kDontNeedShellEscapeChars) == std::string::npos) {
    // only contains chars that don't need quotes; it's fine
    return src;
  } else if (src.find('\'') == std::string::npos) {  // NOLINT
    // no single quotes; just wrap it in single quotes
    return "'" + src + "'";
  } else {
    // needs double quote escaping
    std::string result = "\"";
    for (const char c : src) {
      switch (c) {
        case '\\':
        case '$':
        case '"':
        case '`':
          result.push_back('\\');
      }
      result.push_back(c);
    }
    result.push_back('"');
    return result;
  }
}
}  // namespace

}  // namespace acceleration
}  // namespace tflite
<|endoftext|>


<commit_before>#pragma once

#include <string>

{% for item in c.namespace %}namespace {{item}} { {% endfor %}

struct {{c.name}}
{
{%- for item in c.items %}
    {% if item.optional %}optional<{% endif %}{{item.type}}{%if item.optional %}>{% endif %} {{item.name}}{% if item.default %} = "{{item.default}}"{% endif %};
{%- endfor %}

private:
    friend class nanojson::detail::json_traits<{{c.name}}>;

    void assign(nanojson::value const& src) {
        nanojson::object obj = src.get<nanojson::object>();
        {{c.name}} dst;
        {%- for itm in c.items %}
        {% if itm.optional %}if (obj.count("{{itm.tag}}") > 0) {% endif %}dst.{{itm.name}} = *nanojson::get<decltype(dst.{{itm.name}})>(obj.at("{{itm.tag}}"));
        {%- endfor %}
        *this = std::move(dst);
    }

    nanojson::value as_json() const {
        nanojson::object dst;
        {%- for itm in c.items %}
        dst["{{itm.tag}}"] = nanojson::make_value({{itm.name}});
        {%- endfor %}
        return nanojson::value(std::move(dst));
    }
};

{% for item in c.namespace %}} {% endfor %}// namespace {{'::'.join(c.namespace)}};
<commit_msg>Update template.hpp<commit_after>#pragma once

#include <string>

{% for item in c.namespace -%}
namespace {{item}} {
{%- endfor %}

struct {{c.name}}
{
{%- for item in c.items %}
    {% if item.optional %}optional<{% endif %}{{item.type}}{%if item.optional %}>{% endif %} {{item.name}}{% if item.default %} = "{{item.default}}"{% endif %};
{%- endfor %}

private:
    friend class nanojson::detail::json_traits<{{c.name}}>;

    void assign(nanojson::value const& src) {
        nanojson::object obj = src.get<nanojson::object>();
        {{c.name}} dst;
        {%- for itm in c.items %}
        {% if itm.optional %}if (obj.count("{{itm.tag}}") > 0) {% endif %}dst.{{itm.name}} = *nanojson::get<decltype(dst.{{itm.name}})>(obj.at("{{itm.tag}}"));
        {%- endfor %}
        *this = std::move(dst);
    }

    nanojson::value as_json() const {
        nanojson::object dst;
        {%- for itm in c.items %}
        dst["{{itm.tag}}"] = nanojson::make_value({{itm.name}});
        {%- endfor %}
        return nanojson::value(std::move(dst));
    }
};

{% for item in c.namespace %}} {% endfor %}// namespace {{'::'.join(c.namespace)}};
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Charles J. Cliffe

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "SoapyRTLSDR.hpp"
#include <algorithm>
#include <climits> //SHRT_MAX
#include <cstring> // memcpy

SoapySDR::Stream *SoapyRTLSDR::setupStream(
        const int direction,
        const std::string &format,
        const std::vector<size_t> &channels,
        const SoapySDR::Kwargs &args)
{
    if (direction != SOAPY_SDR_RX)
    {
        throw std::runtime_error("RTL-SDR is RX only, use SOAPY_SDR_RX");
    }

    //check the channel configuration
    if (channels.size() > 1 or (channels.size() > 0 and channels.at(0) != 0))
    {
        throw std::runtime_error("setupStream invalid channel selection");
    }

    //check the format
    if (format == "CF32")
    {
        SoapySDR_log(SOAPY_SDR_INFO, "Using format CF32.");
        rxFormat = RTL_RX_FORMAT_FLOAT32;
    }
    else if (format == "CS16")
    {
        SoapySDR_log(SOAPY_SDR_INFO, "Using format CS16.");
        rxFormat = RTL_RX_FORMAT_INT16;
    }
    else if (format == "CS8") {
        SoapySDR_log(SOAPY_SDR_INFO, "Using format CS8.");
        rxFormat = RTL_RX_FORMAT_INT8;
    }
    else
    {
        throw std::runtime_error(
                "setupStream invalid format '" + format
                        + "' -- Only CS8, CS16 and CF32 are supported by SoapyRTLSDR module.");
    }

    if (rxFormat != RTL_RX_FORMAT_INT8 && !_lut_32f.size())
    {
        SoapySDR_logf(SOAPY_SDR_DEBUG, "Generating RTL-SDR lookup tables");
        // create lookup tables
        for (unsigned int i = 0; i <= 0xffff; i++)
        {
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
            std::complex<float> v32f, vs32f;

            v32f.real((float(i & 0xff) - 127.4f) * (1.0f / 128.0f));
            v32f.imag((float(i >> 8) - 127.4f) * (1.0f / 128.0f));
            _lut_32f.push_back(v32f);

            vs32f.real(v32f.imag());
            vs32f.imag(v32f.real());
            _lut_swap_32f.push_back(vs32f);

            std::complex<int16_t> v16i, vs16i;

            v16i.real(int16_t((float(SHRT_MAX) * ((float(i & 0xff) - 127.4f) * (1.0f / 128.0f)))));
            v16i.imag(int16_t((float(SHRT_MAX) * ((float(i >> 8) - 127.4f) * (1.0f / 128.0f)))));
            _lut_16i.push_back(v16i);

            vs16i.real(vs16i.imag());
            vs16i.imag(vs16i.real());
            _lut_swap_16i.push_back(vs16i);

#else // BIG_ENDIAN
#error  TODO
            //        tmp_swap.imag = tmp.real = (float(i >> 8) - 127.4f) * (1.0f/128.0f);
            //        tmp_swap.real = tmp.imag = (float(i & 0xff) - 127.4f) * (1.0f/128.0f);
            //        _lut.push_back(tmp);
            //        _lut_swap.push_back(tmp_swap);
#endif
        }
    }

    bufferSize = bufferLength * numBuffers;
    iq_buffer.resize(bufferSize);

    return (SoapySDR::Stream *) this;
}

void SoapyRTLSDR::closeStream(SoapySDR::Stream *stream)
{

}

size_t SoapyRTLSDR::getStreamMTU(SoapySDR::Stream *stream) const
{
    return bufferSize / 2;
}

int SoapyRTLSDR::activateStream(
        SoapySDR::Stream *stream,
        const int flags,
        const long long timeNs,
        const size_t numElems)
{
    resetBuffer = true;
    return 0;
}

int SoapyRTLSDR::deactivateStream(SoapySDR::Stream *stream, const int flags, const long long timeNs)
{
    return 0;
}

int SoapyRTLSDR::readStream(
        SoapySDR::Stream *stream,
        void * const *buffs,
        const size_t numElems,
        int &flags,
        long long &timeNs,
        const long timeoutUs)
{
    //this is the user's buffer for channel 0
    void *buff0 = buffs[0];

    if (resetBuffer)
    {
        resetBuffer = false;
        bufferedElems = 0;
        rtlsdr_reset_buffer(dev);
    }

    int n_read = 0;

    //are elements left in the buffer? if not, do a new read.
    if (bufferedElems == 0)
    {
        //receive into temp buffer
        rtlsdr_read_sync(dev, &iq_buffer[0], bufferLength * numBuffers, &n_read);
        bufferedElems = n_read / 2;
        bufferedElemOffset = 0;
    }

    size_t returnedElems = std::min((int) bufferedElems, (int) numElems);

    int buffer_ofs = (bufferedElemOffset * 2);

    //convert into user's buff0
    if (rxFormat == RTL_RX_FORMAT_FLOAT32)
    {
        float *ftarget = (float *) buff0;
        std::complex<float> tmp;
        if (iqSwap)
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_swap_32f[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                ftarget[i * 2] = tmp.real();
                ftarget[i * 2 + 1] = tmp.imag();
            }
        }
        else
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_32f[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                ftarget[i * 2] = tmp.real();
                ftarget[i * 2 + 1] = tmp.imag();
            }
        }
    }
    else if (rxFormat == RTL_RX_FORMAT_INT16)
    {
        int16_t *itarget = (int16_t *) buff0;
        std::complex<int16_t> tmp;
        if (iqSwap)
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_swap_16i[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                itarget[i * 2] = tmp.real();
                itarget[i * 2 + 1] = tmp.imag();
            }
        }
        else
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_16i[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                itarget[i * 2] = tmp.real();
                itarget[i * 2 + 1] = tmp.imag();
            }
        }
    }
    else if (rxFormat == RTL_RX_FORMAT_INT8)
    {
        int8_t *itarget = (int8_t *) buff0;
        if (iqSwap)
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                itarget[i * 2] = iq_buffer[buffer_ofs + i * 2 + 1];
                itarget[i * 2 + 1] = iq_buffer[buffer_ofs + i * 2];
            }
        }
        else
        {
            memcpy(itarget, &iq_buffer[buffer_ofs], returnedElems * 2);
        }
    }

    //bump variables for next call into readStream
    bufferedElems -= returnedElems;
    bufferedElemOffset += returnedElems;

    //return number of elements written to buff0
    return returnedElems;
}
<commit_msg>Fix CS8; remembered input isn't signed :)<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Charles J. Cliffe

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "SoapyRTLSDR.hpp"
#include <algorithm>
#include <climits> //SHRT_MAX
#include <cstring> // memcpy

SoapySDR::Stream *SoapyRTLSDR::setupStream(
        const int direction,
        const std::string &format,
        const std::vector<size_t> &channels,
        const SoapySDR::Kwargs &args)
{
    if (direction != SOAPY_SDR_RX)
    {
        throw std::runtime_error("RTL-SDR is RX only, use SOAPY_SDR_RX");
    }

    //check the channel configuration
    if (channels.size() > 1 or (channels.size() > 0 and channels.at(0) != 0))
    {
        throw std::runtime_error("setupStream invalid channel selection");
    }

    //check the format
    if (format == "CF32")
    {
        SoapySDR_log(SOAPY_SDR_INFO, "Using format CF32.");
        rxFormat = RTL_RX_FORMAT_FLOAT32;
    }
    else if (format == "CS16")
    {
        SoapySDR_log(SOAPY_SDR_INFO, "Using format CS16.");
        rxFormat = RTL_RX_FORMAT_INT16;
    }
    else if (format == "CS8") {
        SoapySDR_log(SOAPY_SDR_INFO, "Using format CS8.");
        rxFormat = RTL_RX_FORMAT_INT8;
    }
    else
    {
        throw std::runtime_error(
                "setupStream invalid format '" + format
                        + "' -- Only CS8, CS16 and CF32 are supported by SoapyRTLSDR module.");
    }

    if (rxFormat != RTL_RX_FORMAT_INT8 && !_lut_32f.size())
    {
        SoapySDR_logf(SOAPY_SDR_DEBUG, "Generating RTL-SDR lookup tables");
        // create lookup tables
        for (unsigned int i = 0; i <= 0xffff; i++)
        {
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
            std::complex<float> v32f, vs32f;

            v32f.real((float(i & 0xff) - 127.4f) * (1.0f / 128.0f));
            v32f.imag((float(i >> 8) - 127.4f) * (1.0f / 128.0f));
            _lut_32f.push_back(v32f);

            vs32f.real(v32f.imag());
            vs32f.imag(v32f.real());
            _lut_swap_32f.push_back(vs32f);

            std::complex<int16_t> v16i, vs16i;

            v16i.real(int16_t((float(SHRT_MAX) * ((float(i & 0xff) - 127.4f) * (1.0f / 128.0f)))));
            v16i.imag(int16_t((float(SHRT_MAX) * ((float(i >> 8) - 127.4f) * (1.0f / 128.0f)))));
            _lut_16i.push_back(v16i);

            vs16i.real(vs16i.imag());
            vs16i.imag(vs16i.real());
            _lut_swap_16i.push_back(vs16i);

#else // BIG_ENDIAN
#error  TODO
            //        tmp_swap.imag = tmp.real = (float(i >> 8) - 127.4f) * (1.0f/128.0f);
            //        tmp_swap.real = tmp.imag = (float(i & 0xff) - 127.4f) * (1.0f/128.0f);
            //        _lut.push_back(tmp);
            //        _lut_swap.push_back(tmp_swap);
#endif
        }
    }

    bufferSize = bufferLength * numBuffers;
    iq_buffer.resize(bufferSize);

    return (SoapySDR::Stream *) this;
}

void SoapyRTLSDR::closeStream(SoapySDR::Stream *stream)
{

}

size_t SoapyRTLSDR::getStreamMTU(SoapySDR::Stream *stream) const
{
    return bufferSize / 2;
}

int SoapyRTLSDR::activateStream(
        SoapySDR::Stream *stream,
        const int flags,
        const long long timeNs,
        const size_t numElems)
{
    resetBuffer = true;
    return 0;
}

int SoapyRTLSDR::deactivateStream(SoapySDR::Stream *stream, const int flags, const long long timeNs)
{
    return 0;
}

int SoapyRTLSDR::readStream(
        SoapySDR::Stream *stream,
        void * const *buffs,
        const size_t numElems,
        int &flags,
        long long &timeNs,
        const long timeoutUs)
{
    //this is the user's buffer for channel 0
    void *buff0 = buffs[0];

    if (resetBuffer)
    {
        resetBuffer = false;
        bufferedElems = 0;
        rtlsdr_reset_buffer(dev);
    }

    int n_read = 0;

    //are elements left in the buffer? if not, do a new read.
    if (bufferedElems == 0)
    {
        //receive into temp buffer
        rtlsdr_read_sync(dev, &iq_buffer[0], bufferLength * numBuffers, &n_read);
        bufferedElems = n_read / 2;
        bufferedElemOffset = 0;
    }

    size_t returnedElems = std::min((int) bufferedElems, (int) numElems);

    int buffer_ofs = (bufferedElemOffset * 2);

    //convert into user's buff0
    if (rxFormat == RTL_RX_FORMAT_FLOAT32)
    {
        float *ftarget = (float *) buff0;
        std::complex<float> tmp;
        if (iqSwap)
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_swap_32f[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                ftarget[i * 2] = tmp.real();
                ftarget[i * 2 + 1] = tmp.imag();
            }
        }
        else
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_32f[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                ftarget[i * 2] = tmp.real();
                ftarget[i * 2 + 1] = tmp.imag();
            }
        }
    }
    else if (rxFormat == RTL_RX_FORMAT_INT16)
    {
        int16_t *itarget = (int16_t *) buff0;
        std::complex<int16_t> tmp;
        if (iqSwap)
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_swap_16i[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                itarget[i * 2] = tmp.real();
                itarget[i * 2 + 1] = tmp.imag();
            }
        }
        else
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                tmp = _lut_16i[*((uint16_t*) &iq_buffer[buffer_ofs + 2 * i])];
                itarget[i * 2] = tmp.real();
                itarget[i * 2 + 1] = tmp.imag();
            }
        }
    }
    else if (rxFormat == RTL_RX_FORMAT_INT8)
    {
        int8_t *itarget = (int8_t *) buff0;
        if (iqSwap)
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                itarget[i * 2] = iq_buffer[buffer_ofs + i * 2 + 1]-127;
                itarget[i * 2 + 1] = iq_buffer[buffer_ofs + i * 2]-127;
            }
        }
        else
        {
            for (size_t i = 0; i < returnedElems; i++)
            {
                itarget[i * 2] = iq_buffer[buffer_ofs + i * 2]-127;
                itarget[i * 2 + 1] = iq_buffer[buffer_ofs + i * 2 + 1]-127;
            }
        }
    }

    //bump variables for next call into readStream
    bufferedElems -= returnedElems;
    bufferedElemOffset += returnedElems;

    //return number of elements written to buff0
    return returnedElems;
}
<|endoftext|>