<commit_before>#ifdef WIN32
	#include <intrin.h>
#endif
#include "test.hpp"
#include "structure/treenode.hpp"
#include <unordered_set>

namespace spn {
	namespace test {
		namespace {
			struct TestNode;
			using SPNode = std::shared_ptr<TestNode>;
			using WPNode = std::weak_ptr<TestNode>;
			using SPNodeV = std::vector<SPNode>;
			struct TestNode : std::enable_shared_from_this<TestNode> {
				SPNodeV		child;
				WPNode		parent;
				int			value;

				enum class Iterate {
					ReturnFromChild,
					StepIn,
					Next,
					Quit
				};
				TestNode(int val): value(val) {}
				void addChild(const SPNode& nd) {
					ASSERT_TRUE(std::find(child.begin(), child.end(), nd) == child.end());
					child.push_back(nd);
					ASSERT_FALSE(nd->getParent());
					nd->parent = shared_from_this();
				}
				void removeChild(const SPNode& nd) {
					auto itr = std::find(child.begin(), child.end(), nd);
					ASSERT_TRUE(itr != child.end());
					child.erase(itr);
					ASSERT_EQ(nd->getParent().get(), this);
					nd->parent = WPNode();
				}
				template <class Callback>
				void iterateDepthFirst(Callback&& cb, int depth=0) {
					cb(*this, depth);
					for(auto& c : child)
						c->iterateDepthFirst(std::forward<Callback>(cb), depth+1);
				}
				SPNode getChild() const {
					if(child.empty())
						return SPNode();
					return child[0];
				}
				SPNode getParent() {
					return parent.lock();
				}
			};

			class TreeNode_t : public TreeNode<TreeNode_t> {
				public:
					int		value;
					TreeNode_t(int v): value(v) {}
			};
			using SPTreeNode = std::shared_ptr<TreeNode_t>;

			void CheckParent(const SPTreeNode& nd) {
				auto c = nd->getChild();
				while(c) {
					// 子ノードの親をチェック
					auto p = c->getParent();
					ASSERT_EQ(p.get(), nd.get());
					// 下層のノードを再帰的にチェック
					CheckParent(c);
					// 兄弟ノードをチェック
					c = c->getSibling();
				}
			}
		}
		class TreeNodeTest : public RandomTestInitializer {};
		template <class A, class B>
		void CheckEqual(const A& a, const B& b) {
			ASSERT_EQ(a.size(), b.size());
			int nN = a.size();
			for(int i=0 ; i<nN ; i++)
				ASSERT_EQ(a[i]->value, b[i]->value);
		}
		template <class T>
		class TestTree {
			using SP = std::shared_ptr<T>;
			using VEC = std::vector<SP>;
			SP		_spRoot;
			VEC		_spArray;

			void _reflArray() {
				_spArray = plain();
			}
			public:
				using Type = T;
				TestTree(int value): _spRoot(std::make_shared<T>(value)) {
					_reflArray();
				}
				//! 要素の追加
				void add(int n, const SP& node) {
					_spArray.at(n)->addChild(node);
					_reflArray();
				}
				//! 要素の削除
				SP rem(int n) {
					SP sp = _spArray.at(n);
					if(auto pr = sp->getParent()) {
						pr->removeChild(sp);
					} else {
						_spRoot = sp->getChild();
						EXPECT_NE(static_cast<T*>(nullptr), _spRoot.get());
					}
					_reflArray();
					return std::move(sp);
				}
				//! 要素の入れ替え
				SP swapAt(int from, int to) {
					auto node = rem(from);
					add(to % size(), node);
					return std::move(node);
				}

				//! 深度優先で配列展開
				VEC plain() const {
					VEC ret;
					_spRoot->iterateDepthFirst([&ret](auto& nd, int){
						ret.emplace_back(nd.shared_from_this());
						return std::decay_t<decltype(nd)>::Iterate::StepIn;
					});
					return std::move(ret);
				}
				const VEC& getArray() const {
					return _spArray;
				}
				const SP& getRoot() const {
					return _spRoot;
				}
				int size() const {
					return _spArray.size();
				}
		};
		template <class CB>
		int _CallTS(CB&& cb) { return -1; }
		template <class CB, class T, class... Ts>
		int _CallTS(CB&& cb, T& tree, Ts&&... ts) {
			int res = cb(tree);
			_CallTS(std::forward<CB>(cb), std::forward<Ts>(ts)...);
			return res;
		}
		template <class RD, class T, class... Ts>
		void RandomManipulate(RD& rd, int value, T&& t, Ts&&... ts) {
			enum class E_Manip {
				Add,
				Add2,
				Add3,
				Remove,
				Recompose,
				_Num
			};
			// ノードが1つしか無い時は追加オンリー
			E_Manip typ = (t.size() <= 1) ? E_Manip::Add :
							static_cast<E_Manip>(rd.template getUniformRange<int>(0, static_cast<int>(E_Manip::_Num)-1));
			switch(typ) {
				// 新たなノードを追加
				case E_Manip::Add:
				case E_Manip::Add2:
				case E_Manip::Add3: {
					// 挿入箇所を配列から適当に選ぶ
					int at = rd.template getUniformRange<int>(0, t.size()-1);
					// Tree-A
					value = _CallTS([value, at](auto& t){
										t.add(at, std::make_shared<typename std::decay_t<decltype(t)>::Type>(value));
										return value;
									}, std::forward<T>(t), std::forward<Ts>(ts)...);
					// std::cout << boost::format("added: %1% value=%2%\n") % at % value;
					break; }
				// ノードを削除
				case E_Manip::Remove: {
					// ルート以外を選ぶ
					int at = rd.template getUniformRange<int>(1, t.size()-1);
					value = _CallTS([at](auto& t){
										return t.rem(at)->value;
									}, std::forward<T>(t), std::forward<Ts>(ts)...);
					// std::cout << boost::format("removed: %1% value=%2%\n") % at % value;
					break; }
				// ノードを別の場所に繋ぎ変え
				case E_Manip::Recompose: {
					int from = rd.template getUniformRange<int>(1, t.size()-1),
						to = rd.template getUniformRange<int>(0, t.size()-2);
					if(to >= from)
						++to;

					value = _CallTS([from, to](auto& t){
										return t.swapAt(from, to)->value;
									}, std::forward<T>(t), std::forward<Ts>(ts)...);
					// std::cout << boost::format("moved: %1% to %2% value=%3%\n") % from % to % value;
					break; }
				default:
					__assume(0);
			}
		}

		//! print out テスト
		template <class TR>
		void PrintOut(TR& tree) {
			using T = typename TR::Type;
			std::unordered_set<T*> testset;
			tree.getRoot()->iterateDepthFirst([&testset](auto& nd, int d){
				using Ret = typename std::decay_t<decltype(nd)>::Iterate;
				while(d-- > 0)
					std::cout << '\t';
				if(testset.count(&nd) == 0) {
					testset.emplace(&nd);
					std::cout << nd.value << std::endl;
					return Ret::StepIn;
				} else {
					std::cout << '[' << nd.value << ']' << std::endl;
					return Ret::Quit;
				}
			});
		}
		//! 重複ノードに関するテスト
		template <class TR>
		void DuplNodeTest(TR& tree)	{
			using T = typename TR::Type;
			std::unordered_set<T*> testset;
			tree.getRoot()->iterateDepthFirst([&testset](auto& nd, int){
				EXPECT_EQ(testset.count(&nd), 0);
				testset.emplace(&nd);
				return std::decay_t<decltype(nd)>::Iterate::StepIn;
			});
		}
		TEST_F(TreeNodeTest, General) {
			auto rd = getRand();
			// TreeNodeと、子を配列で持つノードでそれぞれツリーを作成
			TestTree<TestNode>		treeA(0);		// 確認用
			TestTree<TreeNode_t>	treeB(0);		// テスト対象
			// ランダムにノード操作
			constexpr int N_Manipulation = 100;
			for(int i=1 ; i<N_Manipulation ; i++)
				RandomManipulate(rd, i, treeA, treeB);

			// 親ノードの接続確認
			CheckParent(treeB.getRoot());
			// Cloneしたツリーでも確認
			CheckParent(treeB.getRoot()->clone());
			ASSERT_EQ(treeA.size(), treeB.size());
			// 2種類のツリーで比較
			// (深度優先で巡回した時に同じ順番でノードが取り出せる筈)
			CheckEqual(treeA.getArray(), treeB.getArray());
		}
	}
}

<commit_msg>TreeNode: シリアライズのテストコード追加<commit_after>#ifdef WIN32
	#include <intrin.h>
#endif
#include "test.hpp"
#include "structure/treenode.hpp"
#include <unordered_set>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include "../serialization/smart_ptr.hpp"

namespace spn {
	namespace test {
		namespace {
			struct TestNode;
			using SPNode = std::shared_ptr<TestNode>;
			using WPNode = std::weak_ptr<TestNode>;
			using SPNodeV = std::vector<SPNode>;
			struct TestNode : std::enable_shared_from_this<TestNode> {
				SPNodeV		child;
				WPNode		parent;
				int			value;

				enum class Iterate {
					ReturnFromChild,
					StepIn,
					Next,
					Quit
				};
				TestNode(int val): value(val) {}
				void addChild(const SPNode& nd) {
					ASSERT_TRUE(std::find(child.begin(), child.end(), nd) == child.end());
					child.push_back(nd);
					ASSERT_FALSE(nd->getParent());
					nd->parent = shared_from_this();
				}
				void removeChild(const SPNode& nd) {
					auto itr = std::find(child.begin(), child.end(), nd);
					ASSERT_TRUE(itr != child.end());
					child.erase(itr);
					ASSERT_EQ(nd->getParent().get(), this);
					nd->parent = WPNode();
				}
				template <class Callback>
				void iterateDepthFirst(Callback&& cb, int depth=0) {
					cb(*this, depth);
					for(auto& c : child)
						c->iterateDepthFirst(std::forward<Callback>(cb), depth+1);
				}
				SPNode getChild() const {
					if(child.empty())
						return SPNode();
					return child[0];
				}
				SPNode getParent() {
					return parent.lock();
				}
			};

			class TreeNode_t : public TreeNode<TreeNode_t> {
				using base_t = TreeNode<TreeNode_t>;
				private:
					friend class boost::serialization::access;
					template <class Ar>
					void serialize(Ar& ar, const unsigned int) {
						ar	& BOOST_SERIALIZATION_BASE_OBJECT_NVP(base_t);
					}
				public:
					int		value;
					TreeNode_t(int v): value(v) {}
			};
			using SPTreeNode = std::shared_ptr<TreeNode_t>;

			void CheckParent(const SPTreeNode& nd) {
				auto c = nd->getChild();
				while(c) {
					// 子ノードの親をチェック
					auto p = c->getParent();
					ASSERT_EQ(p.get(), nd.get());
					// 下層のノードを再帰的にチェック
					CheckParent(c);
					// 兄弟ノードをチェック
					c = c->getSibling();
				}
			}
		}
		template <class A, class B>
		void CheckEqual(const A& a, const B& b) {
			ASSERT_EQ(a.size(), b.size());
			int nN = a.size();
			for(int i=0 ; i<nN ; i++)
				ASSERT_EQ(a[i]->value, b[i]->value);
		}
		template <class T>
		class TestTree {
			using SP = std::shared_ptr<T>;
			using VEC = std::vector<SP>;
			SP		_spRoot;
			VEC		_spArray;

			void _reflArray() {
				_spArray = plain();
			}
			public:
				using Type = T;
				TestTree(int value): _spRoot(std::make_shared<T>(value)) {
					_reflArray();
				}
				//! 要素の追加
				void add(int n, const SP& node) {
					_spArray.at(n)->addChild(node);
					_reflArray();
				}
				//! 要素の削除
				SP rem(int n) {
					SP sp = _spArray.at(n);
					if(auto pr = sp->getParent()) {
						pr->removeChild(sp);
					} else {
						_spRoot = sp->getChild();
						EXPECT_NE(static_cast<T*>(nullptr), _spRoot.get());
					}
					_reflArray();
					return std::move(sp);
				}
				//! 要素の入れ替え
				SP swapAt(int from, int to) {
					auto node = rem(from);
					add(to % size(), node);
					return std::move(node);
				}

				//! 深度優先で配列展開
				VEC plain() const {
					return Plain(_spRoot);
				}
				static VEC Plain(const SP& sp) {
					VEC ret;
					sp->iterateDepthFirst([&ret](auto& nd, int){
						ret.emplace_back(nd.shared_from_this());
						return std::decay_t<decltype(nd)>::Iterate::StepIn;
					});
					return std::move(ret);
				}
				const VEC& getArray() const {
					return _spArray;
				}
				const SP& getRoot() const {
					return _spRoot;
				}
				int size() const {
					return _spArray.size();
				}
		};
		template <class CB>
		int _CallTS(CB&& cb) { return -1; }
		template <class CB, class T, class... Ts>
		int _CallTS(CB&& cb, T& tree, Ts&&... ts) {
			int res = cb(tree);
			_CallTS(std::forward<CB>(cb), std::forward<Ts>(ts)...);
			return res;
		}
		template <class RD, class T, class... Ts>
		void RandomManipulate(RD& rd, int value, T&& t, Ts&&... ts) {
			enum class E_Manip {
				Add,
				Add2,
				Add3,
				Remove,
				Recompose,
				_Num
			};
			// ノードが1つしか無い時は追加オンリー
			E_Manip typ = (t.size() <= 1) ? E_Manip::Add :
							static_cast<E_Manip>(rd.template getUniformRange<int>(0, static_cast<int>(E_Manip::_Num)-1));
			switch(typ) {
				// 新たなノードを追加
				case E_Manip::Add:
				case E_Manip::Add2:
				case E_Manip::Add3: {
					// 挿入箇所を配列から適当に選ぶ
					int at = rd.template getUniformRange<int>(0, t.size()-1);
					// Tree-A
					value = _CallTS([value, at](auto& t){
										t.add(at, std::make_shared<typename std::decay_t<decltype(t)>::Type>(value));
										return value;
									}, std::forward<T>(t), std::forward<Ts>(ts)...);
					// std::cout << boost::format("added: %1% value=%2%\n") % at % value;
					break; }
				// ノードを削除
				case E_Manip::Remove: {
					// ルート以外を選ぶ
					int at = rd.template getUniformRange<int>(1, t.size()-1);
					value = _CallTS([at](auto& t){
										return t.rem(at)->value;
									}, std::forward<T>(t), std::forward<Ts>(ts)...);
					// std::cout << boost::format("removed: %1% value=%2%\n") % at % value;
					break; }
				// ノードを別の場所に繋ぎ変え
				case E_Manip::Recompose: {
					int from = rd.template getUniformRange<int>(1, t.size()-1),
						to = rd.template getUniformRange<int>(0, t.size()-2);
					if(to >= from)
						++to;

					value = _CallTS([from, to](auto& t){
										return t.swapAt(from, to)->value;
									}, std::forward<T>(t), std::forward<Ts>(ts)...);
					// std::cout << boost::format("moved: %1% to %2% value=%3%\n") % from % to % value;
					break; }
				default:
					__assume(0);
			}
		}

		//! print out テスト
		template <class SP>
		void PrintOut(SP& root) {
			using T = typename SP::element_type;
			std::unordered_set<const T*> testset;
			root->iterateDepthFirst([&testset](auto& nd, int d){
				using Ret = typename std::decay_t<decltype(nd)>::Iterate;
				while(d-- > 0)
					std::cout << '\t';
				if(testset.count(&nd) == 0) {
					testset.emplace(&nd);
					std::cout << nd.value << std::endl;
					return Ret::StepIn;
				} else {
					std::cout << '[' << nd.value << ']' << std::endl;
					return Ret::Quit;
				}
			});
		}
		//! 重複ノードに関するテスト
		template <class TR>
		void DuplNodeTest(TR& tree)	{
			using T = typename TR::Type;
			std::unordered_set<T*> testset;
			tree.getRoot()->iterateDepthFirst([&testset](auto& nd, int){
				EXPECT_EQ(testset.count(&nd), 0);
				testset.emplace(&nd);
				return std::decay_t<decltype(nd)>::Iterate::StepIn;
			});
		}
		class TreeNodeTest : public RandomTestInitializer {};
		TEST_F(TreeNodeTest, General) {
			auto rd = getRand();
			// TreeNodeと、子を配列で持つノードでそれぞれツリーを作成
			TestTree<TestNode>		treeA(0);		// 確認用
			TestTree<TreeNode_t>	treeB(0);		// テスト対象
			// ランダムにノード操作
			constexpr int N_Manipulation = 100;
			for(int i=1 ; i<N_Manipulation ; i++)
				RandomManipulate(rd, i, treeA, treeB);

			// 親ノードの接続確認
			CheckParent(treeB.getRoot());
			// Cloneしたツリーでも確認
			CheckParent(treeB.getRoot()->clone());
			ASSERT_EQ(treeA.size(), treeB.size());
			// 2種類のツリーで比較
			// (深度優先で巡回した時に同じ順番でノードが取り出せる筈)
			CheckEqual(treeA.getArray(), treeB.getArray());
		}

		using SerializeTest = TreeNodeTest;
		TEST_F(TreeNodeTest, TreeNode) {
			auto rd = getRand();
			// ランダムなツリーを作る
			TestTree<TreeNode_t>	tree(0);
			constexpr int N_Manipulation = 100;
			for(int i=1 ; i<N_Manipulation ; i++)
				RandomManipulate(rd, i, tree);

			// シリアライズ
			TreeNode_t::Serializer sl(tree.getRoot());
			auto ar0 = TestTree<TreeNode_t>::Plain(sl.getNode());
			std::stringstream ss;
			boost::archive::xml_oarchive oa(ss, boost::archive::no_header);
			oa << boost::serialization::make_nvp("test", sl);
			std::cout << ss.str() << std::endl;

			// デシリアライズ
			boost::archive::xml_iarchive ia(ss, boost::archive::no_header);
			ia >> boost::serialization::make_nvp("test", sl);
			auto ar1 = TestTree<TreeNode_t>::Plain(sl.getNode());

			// シリアライズ前後でデータを比べる
			CheckEqual(ar0, ar1);
		}
	}
}
namespace boost {
	namespace serialization {
		template <class Ar>
		void load_construct_data(Ar& ar, spn::test::TreeNode_t* node, const unsigned int) {
			int value;
			ar & make_nvp("value", value);
			new(node) spn::test::TreeNode_t(value);
		}
		template <class Ar>
		void save_construct_data(Ar& ar, const spn::test::TreeNode_t* node, const unsigned int) {
			ar & make_nvp("value", node->value);
		}
	}
}

<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "jml/utils/exc_check.h"

void
DoOutput(FILE * in, FILE * out)
{
    int len(0);
    char *buffer;

    size_t n = ::fread(&len, sizeof(len), 1, in);
    ExcCheckNotEqual(n, 0, "sizeof(len) must be 4");

    buffer = ::malloc(len + 1);
    n = ::fread(&buffer, sizeof(char), len, in);
    ExcCheckNotEqual(n, 0, "received 0 bytes");

    buffer[len] = 0;

    ::fprintf(out, "%s\n", buffer);
    ::free(buffer);
}

void
DoExit(FILE * in)
{
    int code;

    size_t n = ::fread(&code, sizeof(code), 1, in);
    ExcCheckNotEqual(n, 0, "no exit code received");

    printf("helper: exit with code %d\n", code);

    exit(code);
}

int main(int argc, char *argv[])
{
    /** commands:
        err/out|bytes8|nstring
        xit|code(int)
        abt
    */

    printf("helper: ready\n");
    while (1) {
        char command[3];
        size_t n = ::fread(command, 1, sizeof(command), stdin);
        if (n < 3) {
            if (::feof(stdin)) {
                break;
            }
        }
        if (n == 0) {
            continue;
        }

        if (::strncmp(command, "err", 3) == 0) {
            DoOutput(stdin, stderr);
        }
        else if (::strncmp(command, "out", 3) == 0) {
            DoOutput(stdin, stdout);
        }
        else if (::strncmp(command, "xit", 3) == 0) {
            DoExit(stdin);
        }
        else if (::strncmp(command, "abt", 3) == 0) {
            ::abort();
        }
    }

    return 0;
}
<commit_msg>fixed buffer handling<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "jml/utils/exc_check.h"

void
DoOutput(FILE * in, FILE * out)
{
    int len(0);
    char *buffer;

    size_t n = ::fread(&len, sizeof(len), 1, in);
    ExcCheckNotEqual(n, 0, "sizeof(len) must be 4");

    buffer = (char *) ::malloc(len + 1);
    n = ::fread(buffer, sizeof(char), len, in);
    ExcCheckNotEqual(n, 0, "received 0 bytes");

    buffer[len] = 0;

    ::fprintf(out, "%s\n", buffer);
    ::free(buffer);
}

void
DoExit(FILE * in)
{
    int code;

    size_t n = ::fread(&code, sizeof(code), 1, in);
    ExcCheckNotEqual(n, 0, "no exit code received");

    printf("helper: exit with code %d\n", code);

    exit(code);
}

int main(int argc, char *argv[])
{
    /** commands:
        err/out|bytes8|nstring
        xit|code(int)
        abt
    */

    printf("helper: ready\n");
    while (1) {
        char command[3];
        size_t n = ::fread(command, 1, sizeof(command), stdin);
        if (n < 3) {
            if (::feof(stdin)) {
                break;
            }
        }
        if (n == 0) {
            continue;
        }

        if (::strncmp(command, "err", 3) == 0) {
            DoOutput(stdin, stderr);
        }
        else if (::strncmp(command, "out", 3) == 0) {
            DoOutput(stdin, stdout);
        }
        else if (::strncmp(command, "xit", 3) == 0) {
            DoExit(stdin);
        }
        else if (::strncmp(command, "abt", 3) == 0) {
            ::abort();
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * BirdsEyeTranslationReader.cpp
 *
 *  Created on: Feb 21, 2013
 *      Author: link
 */

#include "BirdsEyeTranslationReader.hpp"
#include "ImageEdgeFilter.hpp"
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
bool horizontalPoint2Compare(cv::Point2f p1, cv::Point2f p2) {
	return p1.x < p2.x;
}

bool verticalPoint2Compare(cv::Point2f p1, cv::Point2f p2) {
	return p1.y < p2.y;
}

cv::Mat drawFeatureHistory(const cv::Mat &newImage,
		std::vector<std::list<cv::Point2f> > featureHistory);

//TODO: rememmber to mke this rotation radius ini valid
BirdsEyeTranslationReader::BirdsEyeTranslationReader(const cv::Mat &homography,
		const FeatureExtractor &extractor, const FeatureTracker &tracker,
		const unsigned int& maxFeatures,
		const std::list<FeatureFilter*>& filters, cv::Point2f rotationCentre,
		const cv::Size& imageSize, const double &margin) :
		_maxFeatures(maxFeatures), _rotationCenter(rotationCentre) {
	_homography = homography.clone();
	_tracker = tracker.constructCopy();
	_extractor = extractor.constructCopy();
	for (std::list<FeatureFilter*>::const_iterator it = filters.begin();
			it != filters.end(); ++it) {
		_filters.push_back((*it)->constructCopy());
	}
	_filters.push_front(new ImageEdgeFilter(homography, imageSize, margin));

}

BirdsEyeTranslationReader::BirdsEyeTranslationReader(
		const BirdsEyeTranslationReader &toCopy) :
		_homography(toCopy._homography), _translations(toCopy._translations), _maxFeatures(
				toCopy._maxFeatures), _rotationCenter(toCopy._rotationCenter) {
	_trackedFeatures = toCopy._trackedFeatures;
	_tracker = toCopy._tracker->constructCopy();
	_extractor = toCopy._extractor->constructCopy();
	for (std::list<FeatureFilter*>::const_iterator it = toCopy._filters.begin();
			it != toCopy._filters.end(); ++it) {
		_filters.push_back((*it)->constructCopy());
	}
}

BirdsEyeTranslationReader::~BirdsEyeTranslationReader() {
	if (NULL != _tracker) {
		delete _tracker;
	}
	if (NULL != _extractor) {
		delete _extractor;
	}
	for (std::list<FeatureFilter*>::const_iterator it = _filters.begin();
			it != _filters.end(); ++it) {
		delete *it;
	}
}

TranslationReader *BirdsEyeTranslationReader::constructCopy() const {
	return new BirdsEyeTranslationReader(*this);
}

cv::Point3f BirdsEyeTranslationReader::readTranslation(const cv::Mat &newFrame,
		const double& rotationAngle) {
	cv::Mat newTransformed;
	cv::Point3f result(0, 0, rotationAngle);
	cv::Mat rotationMatrix = cv::getRotationMatrix2D(_rotationCenter,
			-rotationAngle, 1);
	int vectorHalf = 0;
	cv::warpPerspective(newFrame, newTransformed, _homography, newFrame.size(),
			cv::INTER_LINEAR | cv::WARP_INVERSE_MAP);
	if (!_oldFrame.empty()) {
		_extractor->refillFeatures(_oldFrame, _trackedFeatures, _maxFeatures);
		_tracker->trackFeatures(_oldFrame, newTransformed, _trackedFeatures);
		if (!_trackedFeatures.empty()) {
//			cv::Mat pre = drawFeatureHistory(newTransformed, _trackedFeatures);
//			imshow("c1", pre);
//			imshow("ol", _oldFrame);
			for (std::list<FeatureFilter*>::iterator it = _filters.begin();
					it != _filters.end(); ++it) {
				_trackedFeatures = (*it)->filterFeatures(_trackedFeatures);
			}
//			cv::Mat post = drawFeatureHistory(newTransformed, _trackedFeatures);
//			imshow("c2", post);
//			cv::waitKey(0);
			std::vector<cv::Point2f> translations = computeTranslationVectors(
					rotationMatrix);
			vectorHalf = translations.size() / 2;
			std::nth_element(translations.begin(),
					translations.begin() + vectorHalf, translations.end(),
					horizontalPoint2Compare);
			result.x = translations[vectorHalf].x;
			std::nth_element(translations.begin(),
					translations.begin() + vectorHalf, translations.end(),
					verticalPoint2Compare);
			result.y = translations[vectorHalf].y;
		}
	}
	_oldFrame = newTransformed.clone();
	return result;
}

std::vector<cv::Point2f> BirdsEyeTranslationReader::computeTranslationVectors(
		const cv::Mat& rotationMatrix) {
	std::vector<cv::Point2f> result(_trackedFeatures.size());
	std::vector<cv::Point2f> oldFeatures(_trackedFeatures.size()), newFeatures(
			_trackedFeatures.size());
	std::vector<cv::Point2f> newTransformed(newFeatures.size());

	for (unsigned int i = 0; i < result.size(); ++i) { //Highly susceptible to bugs
		oldFeatures[i] = _trackedFeatures[i].front();
		newFeatures[i] = *(++_trackedFeatures[i].begin());
	}
	std::cerr << _trackedFeatures.size() << std::endl << newFeatures.size()
			<< std::endl << rotationMatrix << std::endl;
	cv::transform(newFeatures, newTransformed, rotationMatrix);
	for (unsigned int i = 0; i < result.size(); ++i) {
		result[i] = newTransformed[i] - oldFeatures[i];
		std::cerr << result[i] << std::endl;
	}

	return result;
}

cv::Mat drawFeatureHistory(const cv::Mat &newImage,
		std::vector<std::list<cv::Point2f> > featureHistory) {
	int radius = 5;
	cv::Mat result = newImage.clone();
	for (int i = 0; i < featureHistory.size(); ++i) {
		cv::circle(result, featureHistory[i].front(), radius,
				cv::Scalar(100, 0, 100), -1, 8, 0);
		std::list<cv::Point2f>::iterator itb = featureHistory[i].begin();
		std::list<cv::Point2f>::iterator ite = itb;
		if (!featureHistory.size() < 2) {
			for (ite++; ite != featureHistory[i].end(); ++ite, ++itb) {
				cv::line(result, *ite, *itb, CV_RGB(100,0,0), 1, CV_AA);
			}
		}
	}
	return result;
}
<commit_msg>Cleaned up BirdsEyeTranslationReader.cpp a bit<commit_after>/*
 * BirdsEyeTranslationReader.cpp
 *
 *  Created on: Feb 21, 2013
 *      Author: link
 */

#include "BirdsEyeTranslationReader.hpp"
#include "ImageEdgeFilter.hpp"
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
bool horizontalPoint2Compare(cv::Point2f p1, cv::Point2f p2) {
	return p1.x < p2.x;
}

bool verticalPoint2Compare(cv::Point2f p1, cv::Point2f p2) {
	return p1.y < p2.y;
}

cv::Mat drawFeatureHistory(const cv::Mat &newImage,
		std::vector<std::list<cv::Point2f> > featureHistory);

//TODO: rememmber to mke this rotation radius ini valid
BirdsEyeTranslationReader::BirdsEyeTranslationReader(const cv::Mat &homography,
		const FeatureExtractor &extractor, const FeatureTracker &tracker,
		const unsigned int& maxFeatures,
		const std::list<FeatureFilter*>& filters, cv::Point2f rotationCentre,
		const cv::Size& imageSize, const double &margin) :
		_maxFeatures(maxFeatures), _rotationCenter(rotationCentre) {
	_homography = homography.clone();
	_tracker = tracker.constructCopy();
	_extractor = extractor.constructCopy();
	for (std::list<FeatureFilter*>::const_iterator it = filters.begin();
			it != filters.end(); ++it) {
		_filters.push_back((*it)->constructCopy());
	}
	_filters.push_front(new ImageEdgeFilter(homography, imageSize, margin));

}

BirdsEyeTranslationReader::BirdsEyeTranslationReader(
		const BirdsEyeTranslationReader &toCopy) :
		_homography(toCopy._homography), _translations(toCopy._translations), _maxFeatures(
				toCopy._maxFeatures), _rotationCenter(toCopy._rotationCenter) {
	_trackedFeatures = toCopy._trackedFeatures;
	_tracker = toCopy._tracker->constructCopy();
	_extractor = toCopy._extractor->constructCopy();
	for (std::list<FeatureFilter*>::const_iterator it = toCopy._filters.begin();
			it != toCopy._filters.end(); ++it) {
		_filters.push_back((*it)->constructCopy());
	}
}

BirdsEyeTranslationReader::~BirdsEyeTranslationReader() {
	if (NULL != _tracker) {
		delete _tracker;
	}
	if (NULL != _extractor) {
		delete _extractor;
	}
	for (std::list<FeatureFilter*>::const_iterator it = _filters.begin();
			it != _filters.end(); ++it) {
		delete *it;
	}
}

TranslationReader *BirdsEyeTranslationReader::constructCopy() const {
	return new BirdsEyeTranslationReader(*this);
}

cv::Point3f BirdsEyeTranslationReader::readTranslation(const cv::Mat &newFrame,
		const double& rotationAngle) {
	cv::Mat newTransformed;
	cv::Point3f result(0, 0, rotationAngle);
	cv::Mat rotationMatrix = cv::getRotationMatrix2D(_rotationCenter,
			-rotationAngle, 1);
	int vectorHalf = 0;
	cv::warpPerspective(newFrame, newTransformed, _homography, newFrame.size(),
			cv::INTER_LINEAR | cv::WARP_INVERSE_MAP);
	if (!_oldFrame.empty()) {
		_extractor->refillFeatures(_oldFrame, _trackedFeatures, _maxFeatures);
		_tracker->trackFeatures(_oldFrame, newTransformed, _trackedFeatures);
		if (!_trackedFeatures.empty()) {
//			cv::Mat pre = drawFeatureHistory(newTransformed, _trackedFeatures);
//			imshow("c1", pre);
//			imshow("ol", _oldFrame);
			for (std::list<FeatureFilter*>::iterator it = _filters.begin();
					it != _filters.end(); ++it) {
				_trackedFeatures = (*it)->filterFeatures(_trackedFeatures);
			}
//			cv::Mat post = drawFeatureHistory(newTransformed, _trackedFeatures);
//			imshow("c2", post);
//			cv::waitKey(0);
			std::vector<cv::Point2f> translations = computeTranslationVectors(
					rotationMatrix);
			vectorHalf = translations.size() / 2;
			std::nth_element(translations.begin(),
					translations.begin() + vectorHalf, translations.end(),
					horizontalPoint2Compare);
			result.x = translations[vectorHalf].x;
			std::nth_element(translations.begin(),
					translations.begin() + vectorHalf, translations.end(),
					verticalPoint2Compare);
			result.y = translations[vectorHalf].y;
		}
	}
	_oldFrame = newTransformed.clone();
	return result;
}

std::vector<cv::Point2f> BirdsEyeTranslationReader::computeTranslationVectors(
		const cv::Mat& rotationMatrix) {
	std::vector<cv::Point2f> result(_trackedFeatures.size());
	std::vector<cv::Point2f> oldFeatures(_trackedFeatures.size()), newFeatures(
			_trackedFeatures.size());
	std::vector<cv::Point2f> newTransformed(newFeatures.size());

	for (unsigned int i = 0; i < result.size(); ++i) { //Highly susceptible to bugs
		oldFeatures[i] = _trackedFeatures[i].front();
		newFeatures[i] = *(++_trackedFeatures[i].begin());
	}

	cv::transform(newFeatures, newTransformed, rotationMatrix);
	for (unsigned int i = 0; i < result.size(); ++i) {
		result[i] = newTransformed[i] - oldFeatures[i];
	}

	return result;
}

cv::Mat drawFeatureHistory(const cv::Mat &newImage,
		std::vector<std::list<cv::Point2f> > featureHistory) {
	int radius = 5;
	cv::Mat result = newImage.clone();
	for (int i = 0; i < featureHistory.size(); ++i) {
		cv::circle(result, featureHistory[i].front(), radius,
				cv::Scalar(100, 0, 100), -1, 8, 0);
		std::list<cv::Point2f>::iterator itb = featureHistory[i].begin();
		std::list<cv::Point2f>::iterator ite = itb;
		if (!featureHistory.size() < 2) {
			for (ite++; ite != featureHistory[i].end(); ++ite, ++itb) {
				cv::line(result, *ite, *itb, CV_RGB(100,0,0), 1, CV_AA);
			}
		}
	}
	return result;
}
<|endoftext|>


<commit_before>/*
This file is part of khmer, https://github.com/dib-lab/khmer/, and is
Copyright (C) 2012-2015, Michigan State University.
Copyright (C) 2015-2016, The Regents of the University of California.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * Neither the name of the Michigan State University nor the names
      of its contributors may be used to endorse or promote products
      derived from this software without specific prior written
      permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
LICENSE (END)

Contact: khmer-project@idyll.org
*/
#include <seqan/seq_io.h> // IWYU pragma: keep
#include <seqan/sequence.h> // IWYU pragma: keep
#include <seqan/stream.h> // IWYU pragma: keep
#include <fstream>

#include "khmer_exception.hh"
#include "read_parsers.hh"

namespace khmer
{

namespace read_parsers
{

void
Read::write_to(std::ostream& output)
{
    if (quality.length() != 0) {
        output << "@" << name << std::endl
               << sequence << std::endl
               << "+" << std::endl
               << quality << std::endl;
    } else {
        output << ">" << name << std::endl
               << sequence << std::endl;
    }
}

struct FastxParser::Handle {
    seqan::SequenceStream stream;
    uint32_t seqan_spin_lock;
};

FastxParser::FastxParser( char const * filename ) : IParser( )
{
    _private = new FastxParser::Handle();
    seqan::open(_private->stream, filename);
    if (!seqan::isGood(_private->stream)) {
        std::string message = "Could not open ";
        message = message + filename + " for reading.";
        throw InvalidStream(message);
    } else if (seqan::atEnd(_private->stream)) {
        std::string message = "File ";
        message = message + filename + " does not contain any sequences!";
        throw InvalidStream(message);
    }
    __asm__ __volatile__ ("" ::: "memory");
    _private->seqan_spin_lock = 0;
}

bool FastxParser::is_complete()
{
    return !seqan::isGood(_private->stream) || seqan::atEnd(_private->stream);
}

Read FastxParser::get_next_read()
{
    Read the_read;
    int ret = -1;
    const char *invalid_read_exc = NULL;
    while (!__sync_bool_compare_and_swap(& _private->seqan_spin_lock, 0, 1));
    bool atEnd = seqan::atEnd(_private->stream);
    if (!atEnd) {
        ret = seqan::readRecord(the_read.name, the_read.sequence,
                                the_read.quality, _private->stream);
        if (ret == 0) {
            // Detect if we're parsing something w/ qualities on the first read
            // only
            if (_num_reads == 0 && the_read.quality.length() != 0) {
                _have_qualities = true;
            }

            // Handle error cases, or increment number of reads on success
            if (the_read.sequence.length() == 0) {
                invalid_read_exc = "Sequence is empty";
            } else if (_have_qualities && (the_read.sequence.length() != \
                                           the_read.quality.length())) {
                invalid_read_exc = "Sequence and quality lengths differ";
            } else {
                _num_reads++;
            }
        }
    }
    __asm__ __volatile__ ("" ::: "memory");
    _private->seqan_spin_lock = 0;
    // Throw any error in the read, even if we're at the end
    if (invalid_read_exc != NULL) {
        throw InvalidRead(invalid_read_exc);
    }
    // Throw NoMoreReadsAvailable if none of the above errors were raised, even
    // if ret == 0
    if (atEnd) {
        throw NoMoreReadsAvailable();
    }
    // Catch-all error in readRecord that isn't one of the above
    if (ret != 0) {
        throw StreamReadError();
    }
    return the_read;
}

FastxParser::~FastxParser()
{
    seqan::close(_private->stream);
    delete _private;
}

IParser * const
IParser::
get_parser(
    std:: string const &ifile_name
)
{
    return new FastxParser(ifile_name.c_str());
}

IParser::
IParser(
)
{
    int regex_rc =
        regcomp(
            &_re_read_2_nosub,
            // ".+(/2| 2:[YN]:[[:digit:]]+:[[:alpha:]]+)$",
            "^.+(/2| 2:[YN]:[[:digit:]]+:[[:alpha:]]+).{0}",
            REG_EXTENDED | REG_NOSUB
        );
    if (regex_rc) {
        throw khmer_exception("Could not compile R2 nosub regex");
    }
    regex_rc =
        regcomp(
            &_re_read_1,
            "^.+(/1| 1:[YN]:[[:digit:]]+:[[:alpha:]]+).{0}", REG_EXTENDED
        );
    if (regex_rc) {
        throw khmer_exception("Could not compile R1 regex");
    }
    regex_rc =
        regcomp(
            &_re_read_2,
            "^.+(/2| 2:[YN]:[[:digit:]]+:[[:alpha:]]+).{0}", REG_EXTENDED
        );
    if (regex_rc) {
        throw khmer_exception("Could not compile R2 regex");
    }
    _num_reads = 0;
    _have_qualities = false;
}

IParser::
~IParser( )
{
    regfree( &_re_read_2_nosub );
    regfree( &_re_read_1 );
    regfree( &_re_read_2 );
}

ReadPair IParser::get_next_read_pair(uint8_t mode)
{
    switch (mode) {
    case IParser::PAIR_MODE_IGNORE_UNPAIRED:
        _get_next_read_pair_in_ignore_mode();
        break;
    case IParser::PAIR_MODE_ERROR_ON_UNPAIRED:
        _get_next_read_pair_in_error_mode();
        break;
    default:
        std::ostringstream oss;
        oss << "Unknown pair reading mode: " << mode;
        throw UnknownPairReadingMode(oss.str());
    }
}

ReadPair IParser::_get_next_read_pair_in_ignore_mode()
{
    ReadPair pair;
    regmatch_t match_1, match_2;

    // Hunt for a read pair until one is found or end of reads is reached.
    while (true) {

        // Toss out all reads which are not marked as first of a pair.
        // Note: We let any exception, which flies out of the following,
        //	 pass through unhandled.
        while (true) {
            pair.first = get_next_read();
            if (!regexec(
                        &_re_read_1, pair.first.name.c_str( ), 1, &match_1, 0
                    )) {
                break;
            }
        }

        // If first read of a pair was found, then insist upon second read.
        // If not found, then restart search for pair.
        // If found, then validate match.
        // If invalid pair, then restart search for pair.
        pair.second = get_next_read();
        if (!regexec(
                    &_re_read_2, pair.second.name.c_str( ), 1, &match_2, 0
                )) {
            if (_is_valid_read_pair(pair, match_1, match_2)) {
                break;
            }
        }

    } // while pair not found

    return pair;
} // _get_next_read_pair_in_ignore_mode

ReadPair IParser::_get_next_read_pair_in_error_mode()
{
    ReadPair pair;
    regmatch_t match_1, match_2;

    // Note: We let any exception, which flies out of the following,
    //	     pass through unhandled.
    pair.first = get_next_read();
    pair.second = get_next_read();

    // Is the first read really the first member of a pair?
    if (REG_NOMATCH == regexec(
                &_re_read_1, pair.first.name.c_str( ), 1, &match_1, 0
            )) {
        throw InvalidReadPair( );
    }
    // Is the second read really the second member of a pair?
    if (REG_NOMATCH == regexec(
                &_re_read_2, pair.second.name.c_str( ), 1, &match_2, 0
            )) {
        throw InvalidReadPair( );
    }

    // Is the pair valid?
    if (!_is_valid_read_pair(pair, match_1, match_2)) {
        throw InvalidReadPair( );
    }

    return pair;
} // _get_next_read_pair_in_error_mode

bool
IParser::
_is_valid_read_pair(
    ReadPair &the_read_pair, regmatch_t &match_1, regmatch_t &match_2
)
{
    return	(match_1.rm_so == match_2.rm_so)
            &&	(match_1.rm_eo == match_2.rm_eo)
            &&	(	the_read_pair.first.name.substr( 0, match_1.rm_so )
                    ==	the_read_pair.second.name.substr( 0, match_1.rm_so ));
}

} // namespace read_parsers

} // namespace khmer

// vim: set ft=cpp sts=4 sw=4 tw=80:
<commit_msg>Fix missing return statement during conflict resolution<commit_after>/*
This file is part of khmer, https://github.com/dib-lab/khmer/, and is
Copyright (C) 2012-2015, Michigan State University.
Copyright (C) 2015-2016, The Regents of the University of California.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * Neither the name of the Michigan State University nor the names
      of its contributors may be used to endorse or promote products
      derived from this software without specific prior written
      permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
LICENSE (END)

Contact: khmer-project@idyll.org
*/
#include <seqan/seq_io.h> // IWYU pragma: keep
#include <seqan/sequence.h> // IWYU pragma: keep
#include <seqan/stream.h> // IWYU pragma: keep
#include <fstream>

#include "khmer_exception.hh"
#include "read_parsers.hh"

namespace khmer
{

namespace read_parsers
{

void
Read::write_to(std::ostream& output)
{
    if (quality.length() != 0) {
        output << "@" << name << std::endl
               << sequence << std::endl
               << "+" << std::endl
               << quality << std::endl;
    } else {
        output << ">" << name << std::endl
               << sequence << std::endl;
    }
}

struct FastxParser::Handle {
    seqan::SequenceStream stream;
    uint32_t seqan_spin_lock;
};

FastxParser::FastxParser( char const * filename ) : IParser( )
{
    _private = new FastxParser::Handle();
    seqan::open(_private->stream, filename);
    if (!seqan::isGood(_private->stream)) {
        std::string message = "Could not open ";
        message = message + filename + " for reading.";
        throw InvalidStream(message);
    } else if (seqan::atEnd(_private->stream)) {
        std::string message = "File ";
        message = message + filename + " does not contain any sequences!";
        throw InvalidStream(message);
    }
    __asm__ __volatile__ ("" ::: "memory");
    _private->seqan_spin_lock = 0;
}

bool FastxParser::is_complete()
{
    return !seqan::isGood(_private->stream) || seqan::atEnd(_private->stream);
}

Read FastxParser::get_next_read()
{
    Read the_read;
    int ret = -1;
    const char *invalid_read_exc = NULL;
    while (!__sync_bool_compare_and_swap(& _private->seqan_spin_lock, 0, 1));
    bool atEnd = seqan::atEnd(_private->stream);
    if (!atEnd) {
        ret = seqan::readRecord(the_read.name, the_read.sequence,
                                the_read.quality, _private->stream);
        if (ret == 0) {
            // Detect if we're parsing something w/ qualities on the first read
            // only
            if (_num_reads == 0 && the_read.quality.length() != 0) {
                _have_qualities = true;
            }

            // Handle error cases, or increment number of reads on success
            if (the_read.sequence.length() == 0) {
                invalid_read_exc = "Sequence is empty";
            } else if (_have_qualities && (the_read.sequence.length() != \
                                           the_read.quality.length())) {
                invalid_read_exc = "Sequence and quality lengths differ";
            } else {
                _num_reads++;
            }
        }
    }
    __asm__ __volatile__ ("" ::: "memory");
    _private->seqan_spin_lock = 0;
    // Throw any error in the read, even if we're at the end
    if (invalid_read_exc != NULL) {
        throw InvalidRead(invalid_read_exc);
    }
    // Throw NoMoreReadsAvailable if none of the above errors were raised, even
    // if ret == 0
    if (atEnd) {
        throw NoMoreReadsAvailable();
    }
    // Catch-all error in readRecord that isn't one of the above
    if (ret != 0) {
        throw StreamReadError();
    }
    return the_read;
}

FastxParser::~FastxParser()
{
    seqan::close(_private->stream);
    delete _private;
}

IParser * const
IParser::
get_parser(
    std:: string const &ifile_name
)
{
    return new FastxParser(ifile_name.c_str());
}

IParser::
IParser(
)
{
    int regex_rc =
        regcomp(
            &_re_read_2_nosub,
            // ".+(/2| 2:[YN]:[[:digit:]]+:[[:alpha:]]+)$",
            "^.+(/2| 2:[YN]:[[:digit:]]+:[[:alpha:]]+).{0}",
            REG_EXTENDED | REG_NOSUB
        );
    if (regex_rc) {
        throw khmer_exception("Could not compile R2 nosub regex");
    }
    regex_rc =
        regcomp(
            &_re_read_1,
            "^.+(/1| 1:[YN]:[[:digit:]]+:[[:alpha:]]+).{0}", REG_EXTENDED
        );
    if (regex_rc) {
        throw khmer_exception("Could not compile R1 regex");
    }
    regex_rc =
        regcomp(
            &_re_read_2,
            "^.+(/2| 2:[YN]:[[:digit:]]+:[[:alpha:]]+).{0}", REG_EXTENDED
        );
    if (regex_rc) {
        throw khmer_exception("Could not compile R2 regex");
    }
    _num_reads = 0;
    _have_qualities = false;
}

IParser::
~IParser( )
{
    regfree( &_re_read_2_nosub );
    regfree( &_re_read_1 );
    regfree( &_re_read_2 );
}

ReadPair IParser::get_next_read_pair(uint8_t mode)
{
    switch (mode) {
    case IParser::PAIR_MODE_IGNORE_UNPAIRED:
        return _get_next_read_pair_in_ignore_mode();
        break;
    case IParser::PAIR_MODE_ERROR_ON_UNPAIRED:
        return _get_next_read_pair_in_error_mode();
        break;
    default:
        std::ostringstream oss;
        oss << "Unknown pair reading mode: " << mode;
        throw UnknownPairReadingMode(oss.str());
    }
}

ReadPair IParser::_get_next_read_pair_in_ignore_mode()
{
    ReadPair pair;
    regmatch_t match_1, match_2;

    // Hunt for a read pair until one is found or end of reads is reached.
    while (true) {

        // Toss out all reads which are not marked as first of a pair.
        // Note: We let any exception, which flies out of the following,
        //	 pass through unhandled.
        while (true) {
            pair.first = get_next_read();
            if (!regexec(
                        &_re_read_1, pair.first.name.c_str( ), 1, &match_1, 0
                    )) {
                break;
            }
        }

        // If first read of a pair was found, then insist upon second read.
        // If not found, then restart search for pair.
        // If found, then validate match.
        // If invalid pair, then restart search for pair.
        pair.second = get_next_read();
        if (!regexec(
                    &_re_read_2, pair.second.name.c_str( ), 1, &match_2, 0
                )) {
            if (_is_valid_read_pair(pair, match_1, match_2)) {
                break;
            }
        }

    } // while pair not found

    return pair;
} // _get_next_read_pair_in_ignore_mode

ReadPair IParser::_get_next_read_pair_in_error_mode()
{
    ReadPair pair;
    regmatch_t match_1, match_2;

    // Note: We let any exception, which flies out of the following,
    //	     pass through unhandled.
    pair.first = get_next_read();
    pair.second = get_next_read();

    // Is the first read really the first member of a pair?
    if (REG_NOMATCH == regexec(
                &_re_read_1, pair.first.name.c_str( ), 1, &match_1, 0
            )) {
        throw InvalidReadPair( );
    }
    // Is the second read really the second member of a pair?
    if (REG_NOMATCH == regexec(
                &_re_read_2, pair.second.name.c_str( ), 1, &match_2, 0
            )) {
        throw InvalidReadPair( );
    }

    // Is the pair valid?
    if (!_is_valid_read_pair(pair, match_1, match_2)) {
        throw InvalidReadPair( );
    }

    return pair;
} // _get_next_read_pair_in_error_mode

bool
IParser::
_is_valid_read_pair(
    ReadPair &the_read_pair, regmatch_t &match_1, regmatch_t &match_2
)
{
    return	(match_1.rm_so == match_2.rm_so)
            &&	(match_1.rm_eo == match_2.rm_eo)
            &&	(	the_read_pair.first.name.substr( 0, match_1.rm_so )
                    ==	the_read_pair.second.name.substr( 0, match_1.rm_so ));
}

} // namespace read_parsers

} // namespace khmer

// vim: set ft=cpp sts=4 sw=4 tw=80:
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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 <map>

#include "config.h"
#include "generator_helpers.h"
#include "node_generator.h"
#include "node_generator_helpers.h"

using grpc::protobuf::Descriptor;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;

namespace grpc_node_generator {
namespace {

// Returns the alias we assign to the module of the given .proto filename
// when importing. Copied entirely from
// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
grpc::string ModuleAlias(const grpc::string filename) {
  // This scheme could technically cause problems if a file includes any 2 of:
  //   foo/bar_baz.proto
  //   foo_bar_baz.proto
  //   foo_bar/baz.proto
  //
  // We'll worry about this problem if/when we actually see it.  This name isn't
  // exposed to users so we can change it later if we need to.
  grpc::string basename = grpc_generator::StripProto(filename);
  basename = grpc_generator::StringReplace(basename, "-", "$");
  basename = grpc_generator::StringReplace(basename, "/", "_");
  basename = grpc_generator::StringReplace(basename, ".", "_");
  return basename + "_pb";
}

// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
  grpc::string name = filename;
  return grpc_generator::StripProto(name) + "_pb.js";
}

// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& from_filename,
                         const grpc::string& to_filename) {
  if (to_filename.find("google/protobuf") == 0) {
    // Well-known types (.proto files in the google/protobuf directory) are
    // assumed to come from the 'google-protobuf' npm package.  We may want to
    // generalize this exception later by letting others put generated code in
    // their own npm packages.
    return "google-protobuf/";
  }
  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
  if (slashes == 0) {
    return "./";
  }
  grpc::string result = "";
  for (size_t i = 0; i < slashes; i++) {
    result += "../";
  }
  return result;
}

// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
                             const grpc::string& to_file) {
  return GetRootPath(from_file, to_file) + to_file;
}

/* Finds all message types used in all services in the file, and returns them
 * as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(
    const FileDescriptor* file) {
  map<grpc::string, const Descriptor*> message_types;
  for (int service_num = 0; service_num < file->service_count();
       service_num++) {
    const ServiceDescriptor* service = file->service(service_num);
    for (int method_num = 0; method_num < service->method_count();
         method_num++) {
      const MethodDescriptor* method = service->method(method_num);
      const Descriptor* input_type = method->input_type();
      const Descriptor* output_type = method->output_type();
      message_types[input_type->full_name()] = input_type;
      message_types[output_type->full_name()] = output_type;
    }
  }
  return message_types;
}

grpc::string MessageIdentifierName(const grpc::string& name) {
  return grpc_generator::StringReplace(name, ".", "_");
}

grpc::string NodeObjectPath(const Descriptor* descriptor) {
  grpc::string module_alias = ModuleAlias(descriptor->file()->name());
  grpc::string name = descriptor->full_name();
  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
  return module_alias + "." + name;
}

// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor* descriptor, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  grpc::string full_name = descriptor->full_name();
  template_vars["identifier_name"] = MessageIdentifierName(full_name);
  template_vars["name"] = full_name;
  template_vars["node_name"] = NodeObjectPath(descriptor);
  // Print the serializer
  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
  out->Indent();
  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
  out->Indent();
  out->Print(template_vars,
             "throw new Error('Expected argument of type $name$');\n");
  out->Outdent();
  out->Print("}\n");
  out->Print("return Buffer.from(arg.serializeBinary());\n");
  out->Outdent();
  out->Print("}\n\n");

  // Print the deserializer
  out->Print(template_vars,
             "function deserialize_$identifier_name$(buffer_arg) {\n");
  out->Indent();
  out->Print(
      template_vars,
      "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
  out->Outdent();
  out->Print("}\n\n");
}

void PrintMethod(const MethodDescriptor* method, Printer* out) {
  const Descriptor* input_type = method->input_type();
  const Descriptor* output_type = method->output_type();
  map<grpc::string, grpc::string> vars;
  vars["service_name"] = method->service()->full_name();
  vars["name"] = method->name();
  vars["input_type"] = NodeObjectPath(input_type);
  vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
  vars["output_type"] = NodeObjectPath(output_type);
  vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
  vars["client_stream"] = method->client_streaming() ? "true" : "false";
  vars["server_stream"] = method->server_streaming() ? "true" : "false";
  out->Print("{\n");
  out->Indent();
  out->Print(vars, "path: '/$service_name$/$name$',\n");
  out->Print(vars, "requestStream: $client_stream$,\n");
  out->Print(vars, "responseStream: $server_stream$,\n");
  out->Print(vars, "requestType: $input_type$,\n");
  out->Print(vars, "responseType: $output_type$,\n");
  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
  out->Outdent();
  out->Print("}");
}

// Prints out the service descriptor object
void PrintService(const ServiceDescriptor* service, Printer* out,
                  const Parameters& params) {
  map<grpc::string, grpc::string> template_vars;
  out->Print(GetNodeComments(service, true).c_str());
  template_vars["name"] = service->name();
  template_vars["full_name"] = service->full_name();
  if (params.generate_package_definition) {
    out->Print(template_vars, "var $name$Service = exports['$full_name$'] = {\n");
  } else {
    out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
  }
  out->Indent();
  for (int i = 0; i < service->method_count(); i++) {
    grpc::string method_name =
        grpc_generator::LowercaseFirstLetter(service->method(i)->name());
    out->Print(GetNodeComments(service->method(i), true).c_str());
    out->Print("$method_name$: ", "method_name", method_name);
    PrintMethod(service->method(i), out);
    out->Print(",\n");
    out->Print(GetNodeComments(service->method(i), false).c_str());
  }
  out->Outdent();
  out->Print("};\n\n");
  if (!params.generate_package_definition) {
    out->Print(template_vars,
               "exports.$name$Client = "
               "grpc.makeGenericClientConstructor($name$Service);\n");
  }
  out->Print(GetNodeComments(service, false).c_str());
}

void PrintImports(const FileDescriptor* file, Printer* out,
                  const Parameters& params) {
  if (!params.generate_package_definition) {
    out->Print("var grpc = require('grpc');\n");
  }
  if (file->message_type_count() > 0) {
    grpc::string file_path =
        GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->name()), "file_path", file_path);
  }

  for (int i = 0; i < file->dependency_count(); i++) {
    grpc::string file_path = GetRelativePath(
        file->name(), GetJSMessageFilename(file->dependency(i)->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->dependency(i)->name()), "file_path",
               file_path);
  }
  out->Print("\n");
}

void PrintTransformers(const FileDescriptor* file, Printer* out) {
  map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
  for (std::map<grpc::string, const Descriptor*>::iterator it =
           messages.begin();
       it != messages.end(); it++) {
    PrintMessageTransformer(it->second, out);
  }
  out->Print("\n");
}

void PrintServices(const FileDescriptor* file, Printer* out,
                   const Parameters& params) {
  for (int i = 0; i < file->service_count(); i++) {
    PrintService(file->service(i), out, params);
  }
}
}  // namespace

grpc::string GenerateFile(const FileDescriptor* file,
                          const Parameters& params) {
  grpc::string output;
  {
    StringOutputStream output_stream(&output);
    Printer out(&output_stream, '$');

    if (file->service_count() == 0) {
      output = "// GENERATED CODE -- NO SERVICES IN PROTO";
      return output;
    }
    out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");

    grpc::string leading_comments = GetNodeComments(file, true);
    if (!leading_comments.empty()) {
      out.Print("// Original file comments:\n");
      out.PrintRaw(leading_comments.c_str());
    }

    out.Print("'use strict';\n");

    PrintImports(file, &out, params);

    PrintTransformers(file, &out);

    PrintServices(file, &out, params);

    out.Print(GetNodeComments(file, false).c_str());
  }
  return output;
}

}  // namespace grpc_node_generator
<commit_msg>grpc-tools: Use PrintRaw when outputting comments<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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 <map>

#include "config.h"
#include "generator_helpers.h"
#include "node_generator.h"
#include "node_generator_helpers.h"

using grpc::protobuf::Descriptor;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;

namespace grpc_node_generator {
namespace {

// Returns the alias we assign to the module of the given .proto filename
// when importing. Copied entirely from
// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
grpc::string ModuleAlias(const grpc::string filename) {
  // This scheme could technically cause problems if a file includes any 2 of:
  //   foo/bar_baz.proto
  //   foo_bar_baz.proto
  //   foo_bar/baz.proto
  //
  // We'll worry about this problem if/when we actually see it.  This name isn't
  // exposed to users so we can change it later if we need to.
  grpc::string basename = grpc_generator::StripProto(filename);
  basename = grpc_generator::StringReplace(basename, "-", "$");
  basename = grpc_generator::StringReplace(basename, "/", "_");
  basename = grpc_generator::StringReplace(basename, ".", "_");
  return basename + "_pb";
}

// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
  grpc::string name = filename;
  return grpc_generator::StripProto(name) + "_pb.js";
}

// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& from_filename,
                         const grpc::string& to_filename) {
  if (to_filename.find("google/protobuf") == 0) {
    // Well-known types (.proto files in the google/protobuf directory) are
    // assumed to come from the 'google-protobuf' npm package.  We may want to
    // generalize this exception later by letting others put generated code in
    // their own npm packages.
    return "google-protobuf/";
  }
  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
  if (slashes == 0) {
    return "./";
  }
  grpc::string result = "";
  for (size_t i = 0; i < slashes; i++) {
    result += "../";
  }
  return result;
}

// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
                             const grpc::string& to_file) {
  return GetRootPath(from_file, to_file) + to_file;
}

/* Finds all message types used in all services in the file, and returns them
 * as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(
    const FileDescriptor* file) {
  map<grpc::string, const Descriptor*> message_types;
  for (int service_num = 0; service_num < file->service_count();
       service_num++) {
    const ServiceDescriptor* service = file->service(service_num);
    for (int method_num = 0; method_num < service->method_count();
         method_num++) {
      const MethodDescriptor* method = service->method(method_num);
      const Descriptor* input_type = method->input_type();
      const Descriptor* output_type = method->output_type();
      message_types[input_type->full_name()] = input_type;
      message_types[output_type->full_name()] = output_type;
    }
  }
  return message_types;
}

grpc::string MessageIdentifierName(const grpc::string& name) {
  return grpc_generator::StringReplace(name, ".", "_");
}

grpc::string NodeObjectPath(const Descriptor* descriptor) {
  grpc::string module_alias = ModuleAlias(descriptor->file()->name());
  grpc::string name = descriptor->full_name();
  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
  return module_alias + "." + name;
}

// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor* descriptor, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  grpc::string full_name = descriptor->full_name();
  template_vars["identifier_name"] = MessageIdentifierName(full_name);
  template_vars["name"] = full_name;
  template_vars["node_name"] = NodeObjectPath(descriptor);
  // Print the serializer
  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
  out->Indent();
  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
  out->Indent();
  out->Print(template_vars,
             "throw new Error('Expected argument of type $name$');\n");
  out->Outdent();
  out->Print("}\n");
  out->Print("return Buffer.from(arg.serializeBinary());\n");
  out->Outdent();
  out->Print("}\n\n");

  // Print the deserializer
  out->Print(template_vars,
             "function deserialize_$identifier_name$(buffer_arg) {\n");
  out->Indent();
  out->Print(
      template_vars,
      "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
  out->Outdent();
  out->Print("}\n\n");
}

void PrintMethod(const MethodDescriptor* method, Printer* out) {
  const Descriptor* input_type = method->input_type();
  const Descriptor* output_type = method->output_type();
  map<grpc::string, grpc::string> vars;
  vars["service_name"] = method->service()->full_name();
  vars["name"] = method->name();
  vars["input_type"] = NodeObjectPath(input_type);
  vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
  vars["output_type"] = NodeObjectPath(output_type);
  vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
  vars["client_stream"] = method->client_streaming() ? "true" : "false";
  vars["server_stream"] = method->server_streaming() ? "true" : "false";
  out->Print("{\n");
  out->Indent();
  out->Print(vars, "path: '/$service_name$/$name$',\n");
  out->Print(vars, "requestStream: $client_stream$,\n");
  out->Print(vars, "responseStream: $server_stream$,\n");
  out->Print(vars, "requestType: $input_type$,\n");
  out->Print(vars, "responseType: $output_type$,\n");
  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
  out->Outdent();
  out->Print("}");
}

// Prints out the service descriptor object
void PrintService(const ServiceDescriptor* service, Printer* out,
                  const Parameters& params) {
  map<grpc::string, grpc::string> template_vars;
  out->PrintRaw(GetNodeComments(service, true).c_str());
  template_vars["name"] = service->name();
  template_vars["full_name"] = service->full_name();
  if (params.generate_package_definition) {
    out->Print(template_vars, "var $name$Service = exports['$full_name$'] = {\n");
  } else {
    out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
  }
  out->Indent();
  for (int i = 0; i < service->method_count(); i++) {
    grpc::string method_name =
        grpc_generator::LowercaseFirstLetter(service->method(i)->name());
    out->PrintRaw(GetNodeComments(service->method(i), true).c_str());
    out->Print("$method_name$: ", "method_name", method_name);
    PrintMethod(service->method(i), out);
    out->Print(",\n");
    out->PrintRaw(GetNodeComments(service->method(i), false).c_str());
  }
  out->Outdent();
  out->Print("};\n\n");
  if (!params.generate_package_definition) {
    out->Print(template_vars,
               "exports.$name$Client = "
               "grpc.makeGenericClientConstructor($name$Service);\n");
  }
  out->PrintRaw(GetNodeComments(service, false).c_str());
}

void PrintImports(const FileDescriptor* file, Printer* out,
                  const Parameters& params) {
  if (!params.generate_package_definition) {
    out->Print("var grpc = require('grpc');\n");
  }
  if (file->message_type_count() > 0) {
    grpc::string file_path =
        GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->name()), "file_path", file_path);
  }

  for (int i = 0; i < file->dependency_count(); i++) {
    grpc::string file_path = GetRelativePath(
        file->name(), GetJSMessageFilename(file->dependency(i)->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->dependency(i)->name()), "file_path",
               file_path);
  }
  out->Print("\n");
}

void PrintTransformers(const FileDescriptor* file, Printer* out) {
  map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
  for (std::map<grpc::string, const Descriptor*>::iterator it =
           messages.begin();
       it != messages.end(); it++) {
    PrintMessageTransformer(it->second, out);
  }
  out->Print("\n");
}

void PrintServices(const FileDescriptor* file, Printer* out,
                   const Parameters& params) {
  for (int i = 0; i < file->service_count(); i++) {
    PrintService(file->service(i), out, params);
  }
}
}  // namespace

grpc::string GenerateFile(const FileDescriptor* file,
                          const Parameters& params) {
  grpc::string output;
  {
    StringOutputStream output_stream(&output);
    Printer out(&output_stream, '$');

    if (file->service_count() == 0) {
      output = "// GENERATED CODE -- NO SERVICES IN PROTO";
      return output;
    }
    out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");

    grpc::string leading_comments = GetNodeComments(file, true);
    if (!leading_comments.empty()) {
      out.Print("// Original file comments:\n");
      out.PrintRaw(leading_comments.c_str());
    }

    out.Print("'use strict';\n");

    PrintImports(file, &out, params);

    PrintTransformers(file, &out);

    PrintServices(file, &out, params);

    out.PrintRaw(GetNodeComments(file, false).c_str());
  }
  return output;
}

}  // namespace grpc_node_generator
<|endoftext|>


<commit_before>#include "nan.h"

#include "onig-reg-exp.h"
#include "onig-result.h"

using ::v8::Exception;
using ::v8::String;

OnigRegExp::OnigRegExp(const string& source) : source_(source) {
  OnigErrorInfo error;
  const UChar* sourceData = (const UChar*)source.data();
  int status = onig_new(&regex_, sourceData, sourceData + source.length(),
                        ONIG_OPTION_CAPTURE_GROUP, ONIG_ENCODING_UTF8,
                        ONIG_SYNTAX_DEFAULT, &error);

  if (status != ONIG_NORMAL) {
    UChar errorString[ONIG_MAX_ERROR_MESSAGE_LEN];
    onig_error_code_to_str(errorString, status, &error);
    ThrowException(Exception::Error(String::New(reinterpret_cast<char*>(errorString))));
  }
}

OnigRegExp::~OnigRegExp() {
  if (regex_) onig_free(regex_);
}

bool OnigRegExp::Contains(const string& value) {
  return source_.find(value) != string::npos;
}

OnigResult* OnigRegExp::Search(const string& searchString, size_t position) {
  int end = searchString.size();
  OnigRegion* region = onig_region_new();
  const UChar* searchData = (const UChar*)searchString.data();
  int status = onig_search(regex_, searchData, searchData + end,
                           searchData + position, searchData + end, region,
                           ONIG_OPTION_NONE);

  if (status != ONIG_MISMATCH) {
    return new OnigResult(region, searchString);
  } else {
    onig_region_free(region, 1);
    return NULL;
  }
}
<commit_msg>regex_ should be initialized to NULL.<commit_after>#include "nan.h"

#include "onig-reg-exp.h"
#include "onig-result.h"

using ::v8::Exception;
using ::v8::String;

OnigRegExp::OnigRegExp(const string& source)
    : source_(source),
      regex_(NULL) {
  OnigErrorInfo error;
  const UChar* sourceData = (const UChar*)source.data();
  int status = onig_new(&regex_, sourceData, sourceData + source.length(),
                        ONIG_OPTION_CAPTURE_GROUP, ONIG_ENCODING_UTF8,
                        ONIG_SYNTAX_DEFAULT, &error);

  if (status != ONIG_NORMAL) {
    UChar errorString[ONIG_MAX_ERROR_MESSAGE_LEN];
    onig_error_code_to_str(errorString, status, &error);
    ThrowException(Exception::Error(String::New(reinterpret_cast<char*>(errorString))));
  }
}

OnigRegExp::~OnigRegExp() {
  if (regex_) onig_free(regex_);
}

bool OnigRegExp::Contains(const string& value) {
  return source_.find(value) != string::npos;
}

OnigResult* OnigRegExp::Search(const string& searchString, size_t position) {
  int end = searchString.size();
  OnigRegion* region = onig_region_new();
  const UChar* searchData = (const UChar*)searchString.data();
  int status = onig_search(regex_, searchData, searchData + end,
                           searchData + position, searchData + end, region,
                           ONIG_OPTION_NONE);

  if (status != ONIG_MISMATCH) {
    return new OnigResult(region, searchString);
  } else {
    onig_region_free(region, 1);
    return NULL;
  }
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include "robot_utils/ros_thread_image.h"

class ROSImageObject: public ROSThreadImage
{
public:
    explicit ROSImageObject(std::string namenew): ROSThreadImage(namenew) {}
    void InternalThreadEntry()
    {
        std::cout << "test" << std::endl;
    }
};

TEST(rosimagetest, testsetname)
{
   ROSImageObject rt("test");
   rt.joinInternalThread();

   rt.setName("newtestname");
   EXPECT_EQ("newtestname", rt.getName());
   EXPECT_FALSE("test" == rt.getName());
}

// Run all the tests that were declared with TEST()
int main(int argc, char **argv)
{
    ros::init(argc, argv, "ros_thread_test");
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Minor cosmetic change<commit_after>#include <gtest/gtest.h>
#include "robot_utils/ros_thread_image.h"

class ROSImageObject: public ROSThreadImage
{
public:
    explicit ROSImageObject(std::string namenew): ROSThreadImage(namenew) {}

    void InternalThreadEntry()
    {
        std::cout << "test" << std::endl;
    }
};

TEST(rosimagetest, testsetname)
{
   ROSImageObject rt("test");
   rt.joinInternalThread();

   rt.setName("newtestname");
   EXPECT_EQ("newtestname", rt.getName());
   EXPECT_FALSE("test" == rt.getName());
}

// Run all the tests that were declared with TEST()
int main(int argc, char **argv)
{
    ros::init(argc, argv, "ros_thread_test");
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 Copyright 2019 Alain Dargelas

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

/*
 * File:   CompileStmt.cpp
 * Author: alain
 *
 * Created on May 14, 2019, 8:03 PM
 */
#include <iostream>
#include "Expression/Value.h"
#include "Expression/ExprBuilder.h"
#include "Design/Enum.h"
#include "Design/Function.h"
#include "Testbench/Property.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/ParseFile.h"
#include "SourceCompile/Compiler.h"
#include "Design/Design.h"
#include "DesignCompile/CompileHelper.h"
#include "CompileDesign.h"
#include "uhdm.h"
#include "expr.h"
#include "UhdmWriter.h"

using namespace SURELOG;

UHDM::any* CompileHelper::compileStmt(FileContent* fC, NodeId the_stmt,
        CompileDesign* compileDesign, UHDM::any* pstmt) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  VObjectType type = fC->Type(the_stmt);
  UHDM::any* stmt = nullptr;
  switch (type) {
  case VObjectType::slStatement_or_null:
  case VObjectType::slStatement:
  case VObjectType::slStatement_item:
  case VObjectType::slImmediate_assertion_statement:
  case VObjectType::slProcedural_assertion_statement: {
	  return compileStmt(fC, fC->Child(the_stmt), compileDesign);
  }
  case VObjectType::slProcedural_timing_control_statement:{
    UHDM::atomic_stmt* dc = compileProceduralTimingControlStmt(fC, the_stmt, compileDesign);
    stmt = dc;
    break;
  }
  case VObjectType::slNonblocking_assignment: {
    NodeId Operator_assignment  = the_stmt;
    UHDM::assignment* assign = compileBlockingAssignment(fC,
                Operator_assignment, false, compileDesign);
    stmt = assign;
    break;
  }
  case VObjectType::slBlocking_assignment: {
    NodeId Operator_assignment = fC->Child(the_stmt);
    UHDM::assignment* assign = compileBlockingAssignment(fC,
                Operator_assignment, true, compileDesign);
    stmt = assign;
    break;
  }
  case VObjectType::slSubroutine_call_statement: {
	  NodeId Subroutine_call = fC->Child(the_stmt);
    UHDM::tf_call* call = compileTfCall(fC, Subroutine_call ,compileDesign);
	  stmt = call;
  	break;
  }
  case VObjectType::slSystem_task: {
    UHDM::tf_call* call = compileTfCall(fC, the_stmt, compileDesign);
    stmt = call;
    break;
  }
  case VObjectType::slConditional_statement: {
	  NodeId Conditional_statement = the_stmt;
	  UHDM::atomic_stmt* cstmt = compileConditionalStmt(fC,
                                   Conditional_statement, compileDesign);
  	stmt = cstmt;
  	break;
  }
  case VObjectType::slCase_statement: {
    NodeId Case_statement = the_stmt;
	  UHDM::atomic_stmt* cstmt = compileCaseStmt(fC,
                                   Case_statement, compileDesign);
  	stmt = cstmt;
    break;
  }
  case VObjectType::slSeq_block: {
	  NodeId item = fC->Child(the_stmt);
	  UHDM::begin* begin = s.MakeBegin();
	  VectorOfany* stmts = s.MakeAnyVec();
	  while (item) {
	    UHDM::any* cstmt = compileStmt(fC, item, compileDesign);
	    if (cstmt)
	      stmts->push_back(cstmt);
	    item = fC->Sibling(item);
  	}
	  begin->Stmts(stmts);
	  stmt = begin;
	  break;
  }
  case VObjectType::slSimple_immediate_assertion_statement: {
    stmt = compileImmediateAssertion(fC, fC->Child(the_stmt), compileDesign);
    break;
  }
  default:
    break;
  }
  return stmt;
}

UHDM::any* CompileHelper::compileImmediateAssertion(FileContent* fC, NodeId the_stmt,
        CompileDesign* compileDesign, UHDM::any* pstmt) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  NodeId Expression = fC->Child(the_stmt);
  NodeId Action_block = fC->Sibling(Expression);
  NodeId if_stmt_id = fC->Child(Action_block);
  NodeId else_stmt_id = fC->Sibling(if_stmt_id);
  UHDM::any* expr = compileExpression(fC, Expression, compileDesign);
  UHDM::any* if_stmt = compileStmt(fC, if_stmt_id, compileDesign);
  UHDM::any* else_stmt = compileStmt(fC, else_stmt_id, compileDesign);
  UHDM::any* stmt = nullptr;
  switch (fC->Type(the_stmt)) {
  case VObjectType::slSimple_immediate_assert_statement: {
    UHDM::immediate_assert* astmt = s.MakeImmediate_assert();
    astmt->Expr((UHDM::expr*) expr);
    astmt->Stmt(if_stmt);
    astmt->Else_stmt(else_stmt);
    stmt = astmt;
    break;
  }
  case VObjectType::slSimple_immediate_assume_statement: {
    UHDM::immediate_assume* astmt = s.MakeImmediate_assume();
    astmt->Expr((UHDM::expr*) expr);
    astmt->Stmt(if_stmt);
    astmt->Else_stmt(else_stmt);
    stmt = astmt;
    break;
  }
  case VObjectType::slSimple_immediate_cover_statement: {
    UHDM::immediate_cover* astmt = s.MakeImmediate_cover();
    astmt->Expr((UHDM::expr*) expr);
    astmt->Stmt(if_stmt);
    stmt = astmt;
    break;
  }
  default:
    break;
  }

  /*
n<o> u<277> t<StringConst> p<278> l<25>
n<> u<278> t<Primary_literal> p<279> c<277> l<25>
n<> u<279> t<Primary> p<280> c<278> l<25>
n<> u<280> t<Expression> p<286> c<279> s<281> l<25>
n<> u<281> t<BinOp_Equiv> p<286> s<285> l<25>
n<0> u<282> t<IntConst> p<283> l<25>
n<> u<283> t<Primary_literal> p<284> c<282> l<25>
n<> u<284> t<Primary> p<285> c<283> l<25>
n<> u<285> t<Expression> p<286> c<284> l<25>
n<> u<286> t<Expression> p<289> c<280> s<288> l<25>
n<> u<287> t<Statement_or_null> p<288> l<25>
n<> u<288> t<Action_block> p<289> c<287> l<25>
n<> u<289> t<Simple_immediate_assert_statement> p<290> c<286> l<25>
*/
  return stmt;
}

UHDM::atomic_stmt* CompileHelper::compileConditionalStmt(FileContent* fC,
        NodeId Conditional_statement,
        CompileDesign* compileDesign) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  NodeId Cond_predicate = fC->Child(Conditional_statement);
  UHDM::any* cond_exp = compileExpression(fC, Cond_predicate, compileDesign);
  NodeId If_branch_stmt = fC->Sibling(Cond_predicate);
  NodeId Else_branch_stmt = fC->Sibling(If_branch_stmt);
  UHDM::atomic_stmt* result_stmt = nullptr;
  if (Else_branch_stmt != 0) {
    UHDM::if_else* cond_stmt = s.MakeIf_else();
    cond_stmt->VpiCondition((UHDM::expr*) cond_exp);
    UHDM::any* if_stmt = compileStmt(fC, If_branch_stmt, compileDesign);
    cond_stmt->VpiStmt(if_stmt);
    UHDM::any* else_stmt = compileStmt(fC, Else_branch_stmt, compileDesign);
    cond_stmt->VpiElseStmt(else_stmt);
    result_stmt = cond_stmt;
  } else {
    UHDM::if_stmt* cond_stmt = s.MakeIf_stmt();
    cond_stmt->VpiCondition((UHDM::expr*) cond_exp);
    UHDM::any* if_stmt = compileStmt(fC, If_branch_stmt, compileDesign);
    cond_stmt->VpiStmt(if_stmt);
    result_stmt = cond_stmt;
  }
  return result_stmt;
}

UHDM::atomic_stmt* CompileHelper::compileEventControlStmt(FileContent* fC,
        NodeId Procedural_timing_control_statement,
        CompileDesign* compileDesign) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  /*
  n<#100> u<70> t<IntConst> p<71> l<7>
  n<> u<71> t<Delay_control> p<72> c<70> l<7>
  n<> u<72> t<Procedural_timing_control> p<88> c<71> s<87> l<7>
  */
  NodeId Procedural_timing_control = fC->Child(Procedural_timing_control_statement);
  NodeId Event_control = fC->Child(Procedural_timing_control);

  NodeId Event_expression = fC->Child(Event_control);
  UHDM::event_control* event = s.MakeEvent_control();
  UHDM::any* exp = compileExpression(fC, Event_expression, compileDesign);
  event->VpiCondition(exp);
  NodeId Statement_or_null = fC->Sibling(Procedural_timing_control);
  event->Stmt(compileStmt(fC, Statement_or_null, compileDesign));
  return event;
}

UHDM::atomic_stmt* CompileHelper::compileCaseStmt(FileContent* fC, NodeId nodeId,
        CompileDesign* compileDesign) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  UHDM::atomic_stmt* result = nullptr;
  NodeId Case_keyword = fC->Child(nodeId);
  NodeId Unique = 0;
  if (fC->Type(Case_keyword) == VObjectType::slUnique_priority) {
    Unique = fC->Child(Case_keyword);
    Case_keyword = fC->Sibling(Case_keyword);
  }
  NodeId Case_type = fC->Child(Case_keyword);
  NodeId Condition  = fC->Sibling(Case_keyword);
  UHDM::any* cond_exp = compileExpression(fC, Condition, compileDesign);
  NodeId Case_item = fC->Sibling(Condition);
  UHDM::case_stmt* case_stmt = s.MakeCase_stmt();
  UHDM::VectorOfcase_item* case_items = s.MakeCase_itemVec();
  case_stmt->Case_items(case_items);
  result = case_stmt;
  case_stmt->VpiCondition((UHDM::expr*) cond_exp);
  VObjectType CaseType = fC->Type(Case_type);
  switch (CaseType) {
    case VObjectType::slCase:
      case_stmt->VpiCaseType(vpiCaseExact);
      break;
    case VObjectType::slCaseX:
      case_stmt->VpiCaseType(vpiCaseX);
      break;
    case VObjectType::slCaseZ:
      case_stmt->VpiCaseType(vpiCaseZ);
      break;
    default:
      break;
  }
  if (Unique) {
    VObjectType UniqueType = fC->Type(Unique);
    switch (UniqueType) {
    case VObjectType::slUnique:
      case_stmt->VpiQualifier(vpiUniqueQualifier);
      break;
    case VObjectType::slUnique0:
      case_stmt->VpiQualifier(vpiNoQualifier);
      break;
    case VObjectType::slPriority:
      case_stmt->VpiQualifier(vpiPriorityQualifier);
      break;
    default:
      break;
    }
  }
  while (Case_item) {
    if (fC->Type(Case_item) == VObjectType::slCase_item) {
      UHDM::case_item* case_item = s.MakeCase_item();
      case_items->push_back(case_item);
      NodeId Expression = fC->Child(Case_item);
      if (fC->Type(Expression) == VObjectType::slExpression) {
        VectorOfany* exprs = s.MakeAnyVec();
        case_item->VpiExprs(exprs);
        while (Expression) {
          if (fC->Type(Expression) == VObjectType::slExpression) {
            // Expr
            UHDM::any* item_exp = compileExpression(fC, Expression, compileDesign);
            if (item_exp) {
              exprs->push_back(item_exp);
            } else {
              std::cout << "HERE\n";
            }
          } else {
            // Stmt
            case_item->Stmt(compileStmt(fC, Expression, compileDesign));
          }
          Expression = fC->Sibling(Expression);
        }
      } else {
        // Default
        case_item->Stmt(compileStmt(fC, Expression, compileDesign));
      }
    }
    Case_item = fC->Sibling(Case_item);
  }

  return result;
}<commit_msg>concat support<commit_after>/*
 Copyright 2019 Alain Dargelas

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

/*
 * File:   CompileStmt.cpp
 * Author: alain
 *
 * Created on May 14, 2019, 8:03 PM
 */
#include <iostream>
#include "Expression/Value.h"
#include "Expression/ExprBuilder.h"
#include "Design/Enum.h"
#include "Design/Function.h"
#include "Testbench/Property.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/ParseFile.h"
#include "SourceCompile/Compiler.h"
#include "Design/Design.h"
#include "DesignCompile/CompileHelper.h"
#include "CompileDesign.h"
#include "uhdm.h"
#include "expr.h"
#include "UhdmWriter.h"

using namespace SURELOG;

UHDM::any* CompileHelper::compileStmt(FileContent* fC, NodeId the_stmt,
        CompileDesign* compileDesign, UHDM::any* pstmt) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  VObjectType type = fC->Type(the_stmt);
  UHDM::any* stmt = nullptr;
  switch (type) {
  case VObjectType::slStatement_or_null:
  case VObjectType::slStatement:
  case VObjectType::slStatement_item:
  case VObjectType::slImmediate_assertion_statement:
  case VObjectType::slProcedural_assertion_statement: {
	  return compileStmt(fC, fC->Child(the_stmt), compileDesign);
  }
  case VObjectType::slProcedural_timing_control_statement:{
    UHDM::atomic_stmt* dc = compileProceduralTimingControlStmt(fC, the_stmt, compileDesign);
    stmt = dc;
    break;
  }
  case VObjectType::slNonblocking_assignment: {
    NodeId Operator_assignment  = the_stmt;
    UHDM::assignment* assign = compileBlockingAssignment(fC,
                Operator_assignment, false, compileDesign);
    stmt = assign;
    break;
  }
  case VObjectType::slBlocking_assignment: {
    NodeId Operator_assignment = fC->Child(the_stmt);
    UHDM::assignment* assign = compileBlockingAssignment(fC,
                Operator_assignment, true, compileDesign);
    stmt = assign;
    break;
  }
  case VObjectType::slSubroutine_call_statement: {
	  NodeId Subroutine_call = fC->Child(the_stmt);
    UHDM::tf_call* call = compileTfCall(fC, Subroutine_call ,compileDesign);
	  stmt = call;
  	break;
  }
  case VObjectType::slSystem_task: {
    UHDM::tf_call* call = compileTfCall(fC, the_stmt, compileDesign);
    stmt = call;
    break;
  }
  case VObjectType::slConditional_statement: {
	  NodeId Conditional_statement = the_stmt;
	  UHDM::atomic_stmt* cstmt = compileConditionalStmt(fC,
                                   Conditional_statement, compileDesign);
  	stmt = cstmt;
  	break;
  }
  case VObjectType::slCase_statement: {
    NodeId Case_statement = the_stmt;
	  UHDM::atomic_stmt* cstmt = compileCaseStmt(fC,
                                   Case_statement, compileDesign);
  	stmt = cstmt;
    break;
  }
  case VObjectType::slSeq_block: {
	  NodeId item = fC->Child(the_stmt);
	  UHDM::begin* begin = s.MakeBegin();
	  VectorOfany* stmts = s.MakeAnyVec();
	  while (item) {
	    UHDM::any* cstmt = compileStmt(fC, item, compileDesign);
	    if (cstmt)
	      stmts->push_back(cstmt);
	    item = fC->Sibling(item);
  	}
	  begin->Stmts(stmts);
	  stmt = begin;
	  break;
  }
  case VObjectType::slSimple_immediate_assertion_statement: {
    stmt = compileImmediateAssertion(fC, fC->Child(the_stmt), compileDesign);
    break;
  }
  default:
    break;
  }
  return stmt;
}

UHDM::any* CompileHelper::compileImmediateAssertion(FileContent* fC, NodeId the_stmt,
        CompileDesign* compileDesign, UHDM::any* pstmt) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  NodeId Expression = fC->Child(the_stmt);
  NodeId Action_block = fC->Sibling(Expression);
  NodeId if_stmt_id = fC->Child(Action_block);
  NodeId else_stmt_id = fC->Sibling(if_stmt_id);
  UHDM::any* expr = compileExpression(fC, Expression, compileDesign);
  UHDM::any* if_stmt = compileStmt(fC, if_stmt_id, compileDesign);
  UHDM::any* else_stmt = compileStmt(fC, else_stmt_id, compileDesign);
  UHDM::any* stmt = nullptr;
  switch (fC->Type(the_stmt)) {
  case VObjectType::slSimple_immediate_assert_statement: {
    UHDM::immediate_assert* astmt = s.MakeImmediate_assert();
    astmt->Expr((UHDM::expr*) expr);
    astmt->Stmt(if_stmt);
    astmt->Else_stmt(else_stmt);
    stmt = astmt;
    break;
  }
  case VObjectType::slSimple_immediate_assume_statement: {
    UHDM::immediate_assume* astmt = s.MakeImmediate_assume();
    astmt->Expr((UHDM::expr*) expr);
    astmt->Stmt(if_stmt);
    astmt->Else_stmt(else_stmt);
    stmt = astmt;
    break;
  }
  case VObjectType::slSimple_immediate_cover_statement: {
    UHDM::immediate_cover* astmt = s.MakeImmediate_cover();
    astmt->Expr((UHDM::expr*) expr);
    astmt->Stmt(if_stmt);
    stmt = astmt;
    break;
  }
  default:
    break;
  }

  /*
n<o> u<277> t<StringConst> p<278> l<25>
n<> u<278> t<Primary_literal> p<279> c<277> l<25>
n<> u<279> t<Primary> p<280> c<278> l<25>
n<> u<280> t<Expression> p<286> c<279> s<281> l<25>
n<> u<281> t<BinOp_Equiv> p<286> s<285> l<25>
n<0> u<282> t<IntConst> p<283> l<25>
n<> u<283> t<Primary_literal> p<284> c<282> l<25>
n<> u<284> t<Primary> p<285> c<283> l<25>
n<> u<285> t<Expression> p<286> c<284> l<25>
n<> u<286> t<Expression> p<289> c<280> s<288> l<25>
n<> u<287> t<Statement_or_null> p<288> l<25>
n<> u<288> t<Action_block> p<289> c<287> l<25>
n<> u<289> t<Simple_immediate_assert_statement> p<290> c<286> l<25>
*/
  return stmt;
}

UHDM::atomic_stmt* CompileHelper::compileConditionalStmt(FileContent* fC,
        NodeId Conditional_statement,
        CompileDesign* compileDesign) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  NodeId Cond_predicate = fC->Child(Conditional_statement);
  UHDM::any* cond_exp = compileExpression(fC, Cond_predicate, compileDesign);
  NodeId If_branch_stmt = fC->Sibling(Cond_predicate);
  NodeId Else_branch_stmt = fC->Sibling(If_branch_stmt);
  UHDM::atomic_stmt* result_stmt = nullptr;
  if (Else_branch_stmt != 0) {
    UHDM::if_else* cond_stmt = s.MakeIf_else();
    cond_stmt->VpiCondition((UHDM::expr*) cond_exp);
    UHDM::any* if_stmt = compileStmt(fC, If_branch_stmt, compileDesign);
    cond_stmt->VpiStmt(if_stmt);
    UHDM::any* else_stmt = compileStmt(fC, Else_branch_stmt, compileDesign);
    cond_stmt->VpiElseStmt(else_stmt);
    result_stmt = cond_stmt;
  } else {
    UHDM::if_stmt* cond_stmt = s.MakeIf_stmt();
    cond_stmt->VpiCondition((UHDM::expr*) cond_exp);
    UHDM::any* if_stmt = compileStmt(fC, If_branch_stmt, compileDesign);
    cond_stmt->VpiStmt(if_stmt);
    result_stmt = cond_stmt;
  }
  return result_stmt;
}

UHDM::atomic_stmt* CompileHelper::compileEventControlStmt(FileContent* fC,
        NodeId Procedural_timing_control_statement,
        CompileDesign* compileDesign) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  /*
  n<#100> u<70> t<IntConst> p<71> l<7>
  n<> u<71> t<Delay_control> p<72> c<70> l<7>
  n<> u<72> t<Procedural_timing_control> p<88> c<71> s<87> l<7>
  */
  NodeId Procedural_timing_control = fC->Child(Procedural_timing_control_statement);
  NodeId Event_control = fC->Child(Procedural_timing_control);

  NodeId Event_expression = fC->Child(Event_control);
  UHDM::event_control* event = s.MakeEvent_control();
  UHDM::any* exp = compileExpression(fC, Event_expression, compileDesign);
  event->VpiCondition(exp);
  NodeId Statement_or_null = fC->Sibling(Procedural_timing_control);
  event->Stmt(compileStmt(fC, Statement_or_null, compileDesign));
  return event;
}

UHDM::atomic_stmt* CompileHelper::compileCaseStmt(FileContent* fC, NodeId nodeId,
        CompileDesign* compileDesign) {
  UHDM::Serializer& s = compileDesign->getSerializer();
  UHDM::atomic_stmt* result = nullptr;
  NodeId Case_keyword = fC->Child(nodeId);
  NodeId Unique = 0;
  if (fC->Type(Case_keyword) == VObjectType::slUnique_priority) {
    Unique = fC->Child(Case_keyword);
    Case_keyword = fC->Sibling(Case_keyword);
  }
  NodeId Case_type = fC->Child(Case_keyword);
  NodeId Condition  = fC->Sibling(Case_keyword);
  UHDM::any* cond_exp = compileExpression(fC, Condition, compileDesign);
  NodeId Case_item = fC->Sibling(Condition);
  UHDM::case_stmt* case_stmt = s.MakeCase_stmt();
  UHDM::VectorOfcase_item* case_items = s.MakeCase_itemVec();
  case_stmt->Case_items(case_items);
  result = case_stmt;
  case_stmt->VpiCondition((UHDM::expr*) cond_exp);
  VObjectType CaseType = fC->Type(Case_type);
  switch (CaseType) {
    case VObjectType::slCase:
      case_stmt->VpiCaseType(vpiCaseExact);
      break;
    case VObjectType::slCaseX:
      case_stmt->VpiCaseType(vpiCaseX);
      break;
    case VObjectType::slCaseZ:
      case_stmt->VpiCaseType(vpiCaseZ);
      break;
    default:
      break;
  }
  if (Unique) {
    VObjectType UniqueType = fC->Type(Unique);
    switch (UniqueType) {
    case VObjectType::slUnique:
      case_stmt->VpiQualifier(vpiUniqueQualifier);
      break;
    case VObjectType::slUnique0:
      case_stmt->VpiQualifier(vpiNoQualifier);
      break;
    case VObjectType::slPriority:
      case_stmt->VpiQualifier(vpiPriorityQualifier);
      break;
    default:
      break;
    }
  }
  while (Case_item) {
    if (fC->Type(Case_item) == VObjectType::slCase_item) {
      UHDM::case_item* case_item = s.MakeCase_item();
      case_items->push_back(case_item);
      NodeId Expression = fC->Child(Case_item);
      if (fC->Type(Expression) == VObjectType::slExpression) {
        VectorOfany* exprs = s.MakeAnyVec();
        case_item->VpiExprs(exprs);
        while (Expression) {
          if (fC->Type(Expression) == VObjectType::slExpression) {
            // Expr
            UHDM::any* item_exp = compileExpression(fC, Expression, compileDesign);
            if (item_exp) {
              exprs->push_back(item_exp);
            } else {
              //std::cout << "HERE\n";
            }
          } else {
            // Stmt
            case_item->Stmt(compileStmt(fC, Expression, compileDesign));
          }
          Expression = fC->Sibling(Expression);
        }
      } else {
        // Default
        case_item->Stmt(compileStmt(fC, Expression, compileDesign));
      }
    }
    Case_item = fC->Sibling(Case_item);
  }

  return result;
}<|endoftext|>


<commit_before>#include "SettingsWindow.hpp"

#include <imgui.h>
#include "../ImGui/Theme.hpp"

using namespace GUI;

SettingsWindow::SettingsWindow() {
    themes.push_back("Default");
}

void SettingsWindow::Show() {
    if (ImGui::Begin("Settings", &visible)) {
        // Show drop down list to select theme.
        if (dropDownItems != nullptr)
            delete[] dropDownItems;
        dropDownItems = new const char*[themes.size()];
        for (std::size_t i=0; i < themes.size(); ++i) {
            dropDownItems[i] = themes[i].c_str();
        }

        ImGui::Combo("Theme", &theme, dropDownItems, themes.size());

        // Clone current theme to create a new theme.
        if (ImGui::Button("Clone")) {
            ImGui::OpenPopup("Theme Name");
            themeName[0] = '\0';
        }

        if (ImGui::BeginPopupModal("Theme Name", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
            ImGui::InputText("Name", themeName, 128);

            if (ImGui::Button("Create")) {
                ImGui::SaveTheme(themeName);
                themes.push_back(themeName);
                ImGui::CloseCurrentPopup();
            }
            ImGui::SameLine();
            if (ImGui::Button("Cancel"))
                ImGui::CloseCurrentPopup();

            ImGui::EndPopup();
        }

        if (theme != 0)
            ImGui::ShowStyleEditor();
    }

    ImGui::End();
}

bool SettingsWindow::IsVisible() const {
    return visible;
}

void SettingsWindow::SetVisible(bool visible) {
    this->visible = visible;
}
<commit_msg>Separator between selecting and editing theme<commit_after>#include "SettingsWindow.hpp"

#include <imgui.h>
#include "../ImGui/Theme.hpp"

using namespace GUI;

SettingsWindow::SettingsWindow() {
    themes.push_back("Default");
}

void SettingsWindow::Show() {
    if (ImGui::Begin("Settings", &visible)) {
        // Show drop down list to select theme.
        if (dropDownItems != nullptr)
            delete[] dropDownItems;
        dropDownItems = new const char*[themes.size()];
        for (std::size_t i=0; i < themes.size(); ++i) {
            dropDownItems[i] = themes[i].c_str();
        }

        ImGui::Combo("Theme", &theme, dropDownItems, themes.size());

        // Clone current theme to create a new theme.
        if (ImGui::Button("Clone")) {
            ImGui::OpenPopup("Theme Name");
            themeName[0] = '\0';
        }

        if (ImGui::BeginPopupModal("Theme Name", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
            ImGui::InputText("Name", themeName, 128);

            if (ImGui::Button("Create")) {
                ImGui::SaveTheme(themeName);
                themes.push_back(themeName);
                ImGui::CloseCurrentPopup();
            }
            ImGui::SameLine();
            if (ImGui::Button("Cancel"))
                ImGui::CloseCurrentPopup();

            ImGui::EndPopup();
        }

        ImGui::Separator();

        // Edit the current theme.
        if (theme != 0)
            ImGui::ShowStyleEditor();
    }

    ImGui::End();
}

bool SettingsWindow::IsVisible() const {
    return visible;
}

void SettingsWindow::SetVisible(bool visible) {
    this->visible = visible;
}
<|endoftext|>