text:
#include "MasterProcessingWorker.h"

#include <iostream>
#include <fstream>
#include <future>
#include <exiv2/exiv2.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/format.hpp>
#include "Base/Error.h"
#include "Ocr/Tesseract/TesseractFactory.h"
#include "Ocr/UninitializedOcrException.h"
#include <boost/algorithm/string.hpp>
#include "PDF/MuPDF.h"
#include "Buffer/ExivMemoryFileBuffer.h"
#include <zlib.h>
#include "MasterLocalFileStatus.h"
#include "MasterMemoryFileStatus.h"

#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

#define TXMP_STRING_TYPE std::string
#define XMP_INCLUDE_XMPFILES 1
#include "XMP.incl_cpp"
#include "XMP.hpp"
#include "XMP_IO.hpp"
#include "XMP/MemoryXMPIO.h"
#include "Base/Version.h"
#include "Buffer/VectorMemoryFileBuffer.h"

const XMP_StringPtr kXMP_NS_OCRAUTOMATOR = "http://leia.io/meta/1.0/Xmp/";
const XMP_StringPtr kXMP_NS_OCRAUTOMATOR_OCR = "http://leia.io/meta/1.0/Xmp/Ocr/";

#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
#  include <fcntl.h>
#  include <io.h>
#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
#  define SET_BINARY_MODE(file)
#endif

const std::vector<char*> Docapost::IA::Tesseract::MasterProcessingWorker::EXIF_FIELD = { (char*)"Exif.Image.DNGPrivateData", (char*)"Exif.Image.CFAPlaneColor", (char*)"Exif.Image.Copyright" };
const char* EXTENSION_EXTRA = ".extra";

Docapost::IA::Tesseract::MasterProcessingWorker::MasterProcessingWorker(OcrFactory& ocr, Docapost::IA::Tesseract::OutputFlags types, int port) :
	BaseProcessingWorker(ocr),
	mOutputTypes(types)
{
	/*PoDoFo::PdfError::EnableDebug(false);
	PoDoFo::PdfError::EnableLogging(false);*/

	SXMPMeta::Initialize();
	XMP_OptionBits options = 0;
#ifdef __linux__
	options |= kXMPFiles_IgnoreLocalText;
#endif
	SXMPFiles::Initialize(options);

	mNetworkThread = new std::thread([this, port]()
	{
		int _port = port;
		while (_port < 65565)
		{
			try
			{
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Try Starting network on port " << _port;
				CatchAllErrorSignals();
				mNetwork = boost::make_shared<Network>(_port);
				mNetwork->onSlaveConnect.connect(boost::bind(&MasterProcessingWorker::OnSlaveConnectHandler, this, _1, _2, _3));

				mNetwork->onSlaveSynchro.connect(boost::bind(&MasterProcessingWorker::OnSlaveSynchroHandler, this, _1, _2, _3, _4));

				mNetwork->onSlaveDisconnect.connect(boost::bind(&MasterProcessingWorker::OnSlaveDisconnectHandler, this, _1, _2));

				mNetwork->InitBroadcastReceiver();
				mNetwork->InitComm();
				mIsNetworkInit = true;
				mNetwork->Start();
				break;
			}
			catch (std::exception &e)
			{
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "/!\\ Unable to start network on port " << _port;
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "/!\\ Error " << e.what();

				if (mNetwork != nullptr)
				{
					mNetwork->Stop();
					mNetwork.reset();
				}
				_port++;
			}
			catch (...)
			{
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "/!\\ Unable to start network on port " << _port;
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "/!\\ Error " << GET_EXCEPTION_NAME;

				if (mNetwork != nullptr)
				{
					mNetwork->Stop();
					mNetwork.reset();
				}
				_port++;
			}
		}
	});
}

const char* kPathSeparator =
#ifdef _WIN32
"\\";
#else
"/";
#endif

fs::path Docapost::IA::Tesseract::MasterProcessingWorker::ConstructNewTextFilePath(fs::path path, std::string ext = ".txt") const
{
	fs::path new_path;

	auto it = mOutputs.find(OutputFlags::Text);
	if (it == mOutputs.end() || it->second == mInput)
	{
		new_path = fs::change_extension(path, ext);
	}
	else
	{
		auto relative_path = fs::relative(path, mInput);

		new_path = fs::absolute(relative_path, it->second);
		if (mOutputTypes & OutputFlags::Flattern)
			new_path = new_path.parent_path() / boost::replace_all_copy(fs::change_extension(relative_path, ext).string(), kPathSeparator, mSeparator);
		else
			new_path = new_path.parent_path() / fs::change_extension(new_path.filename(), ext);

	}
	return new_path;
}

bool Docapost::IA::Tesseract::MasterProcessingWorker::MergeResult(MasterFileStatus* mfile)
{

	MasterLocalFileStatus* file = dynamic_cast<MasterLocalFileStatus*>(mfile);
	if (file == nullptr)
		return true;

	// IF we do not require text writing, just do not merge
	if (!(mOutputTypes & OutputFlags::Text))
	{
		file->isCompleted = true;
		return true;
	}

	if (file->filePosition < 0)
	{
		file->isCompleted = true;
		return true;
	}

	std::lock_guard<std::mutex>(*file->mutex_siblings);
	file->isCompleted = true;
	bool completed = true;
	for (int i = 0; i < file->siblings->size(); i++)
	{
		auto item = (*file->siblings)[i];
		if (item != nullptr)
		{
			if (!item->isCompleted)
			{
				completed = false;
				break;
			}
		}
	}

	if (completed)
	{
		auto new_path = ConstructNewTextFilePath(file->name);
		std::ofstream stream{ new_path.string(), std::ios::out | std::ios::trunc };

		for (int i = 0; i < file->siblings->size(); i++)
		{
			auto item = (*file->siblings)[i];
			if (item != nullptr)
			{
				stream << *(item->result->begin()) << std::endl;
			}
			else
			{
				auto pdf_path = CreatePdfOutputPath(file->name, i);
				auto output_file = ConstructNewTextFilePath(pdf_path);
				if (!fs::exists(output_file))
				{
					stream.close();
					fs::remove(new_path);
					break;
				}
				std::ifstream ifile(output_file.string(), std::ios::in);
				stream << ifile.rdbuf() << std::endl;
			}
		}
	}
	return completed;
}

fs::path Docapost::IA::Tesseract::MasterProcessingWorker::ConstructNewExifFilePath(fs::path path) const
{
	fs::path new_path;

	auto relative_path = fs::relative(path, mInput);
	auto it = mOutputs.find(OutputFlags::Metadata);
	if (it == mOutputs.end() || it->second == mInput)
	{
		return path;
	}
	else
	{
		new_path = fs::absolute(relative_path, it->second);

		if (mOutputTypes & OutputFlags::Flattern)
			new_path = new_path.parent_path() / boost::replace_all_copy(relative_path.string(), kPathSeparator, mSeparator);
		else
			new_path = new_path.parent_path() / new_path.filename();

	}
	return new_path;
}

bool Docapost::IA::Tesseract::MasterProcessingWorker::FileExist(fs::path path) const
{
	auto new_path = ConstructNewTextFilePath(path);

	return fs::exists(new_path);
}

bool Docapost::IA::Tesseract::MasterProcessingWorker::MetadataExist(fs::path path, bool fast) const
{
	auto new_path = ConstructNewExifFilePath(path);

	if (!fs::exists(new_path))
	{
		return false;
	}

	if (fast)
	{
		return fs::exists(new_path);
	}

	try
	{
		SXMPMeta meta;
		SXMPFiles xmpfile;
		auto res1 = xmpfile.OpenFile(new_path.string(), kXMP_UnknownFile, kXMPFiles_OpenForUpdate | kXMPFiles_OpenUseSmartHandler);
		auto res = xmpfile.GetXMP(&meta);

		std::string ns;
		SXMPMeta::RegisterNamespace(kXMP_NS_OCRAUTOMATOR, "OcrAutomator", &ns);
		SXMPMeta::RegisterNamespace(kXMP_NS_OCRAUTOMATOR_OCR, "Ocr", &ns);

		auto ocrName = mOcrFactory.Name();
		if (!meta.DoesPropertyExist(kXMP_NS_OCRAUTOMATOR, "Sections"))
		{
			if (meta.DoesPropertyExist(kXMP_NS_OCRAUTOMATOR, ocrName.c_str()))
			{
				// If the file does not possese a Section, correct it by creating one
				meta.SetProperty(kXMP_NS_OCRAUTOMATOR, "Sections", 0, kXMP_PropValueIsArray);
				meta.AppendArrayItem(kXMP_NS_OCRAUTOMATOR, "Sections", 0, ocrName.c_str(), 0);
				xmpfile.PutXMP(meta);
				xmpfile.CloseFile();
				return true;
			}
			return false;
		}

		if (!meta.DoesPropertyExist(kXMP_NS_OCRAUTOMATOR, ocrName.c_str()))
		{
			return false;
		}

		int nbSections = meta.CountArrayItems(kXMP_NS_OCRAUTOMATOR, "Sections");
		bool sectionExist = false;
		for (int i = 0; i < nbSections; i++)
		{
			std::string section;
			meta.GetArrayItem(kXMP_NS_OCRAUTOMATOR, "Sections", i + 1, &section, 0);
			if (section == ocrName)
			{
				sectionExist = true;
				break;
			}
		}

		return sectionExist;
	}
	catch (XMP_Error& wmp_err)
	{
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "cannot Write XMP : " << wmp_err.GetErrMsg();
	}
	return false;
}

string Docapost::IA::Tesseract::MasterProcessingWorker::CreatePdfOutputPath(fs::path path, int i)
{
	return (boost::format("%s%s%s-%d%d") % path.parent_path().string() % kPathSeparator % fs::change_extension(path.filename(), "").string() % i % mOcrFactory.GetExtension()).str();
}

void Docapost::IA::Tesseract::MasterProcessingWorker::InitPdfMasterFileStatus(MasterFileStatus* file, std::mutex* mutex_siblings, std::vector<MasterFileStatus*>* siblings, int i)
{
	mTotal++;
	file->filePosition = i;
	(*siblings)[i] = file;
	file->siblings = siblings;
	file->mutex_siblings = mutex_siblings;
}

int Docapost::IA::Tesseract::MasterProcessingWorker::AddPdfFile(bool resume, fs::path path)
{
	int nbPages = 0;
	try
	{
		MuPDF::MuPDF pdf;
		nbPages = pdf.GetNbPage(path.string());
	}
	catch (std::runtime_error& err)
	{
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "cannot read pdf: " << path << "\nReason: " << err.what();
		return 0;
	}

	std::mutex* mutex_siblings = new std::mutex();

	std::vector<MasterFileStatus*>* siblings = new std::vector<MasterFileStatus*>(nbPages);

	bool added = false;
	for (int i = 0; i < nbPages; i++)
	{
		bool toProcess = true;
		std::string output_file = CreatePdfOutputPath(path, i);

		if (resume)
		{
			toProcess = false;
			if (mOutputTypes & OutputFlags::Text)
			{
				toProcess = toProcess || !FileExist(output_file);
			}

			if (mOutputTypes & OutputFlags::Metadata)
			{
				toProcess = toProcess || !MetadataExist(output_file, mOutputTypes & OutputFlags::FastScan);
			}

			if (!toProcess)
			{
				mSkip++;
			}
		}

		if (toProcess)
		{
			MasterFileStatus* file = new MasterLocalFileStatus(path.string(), fs::relative(path, mInput).string(), output_file);
			InitPdfMasterFileStatus(file, mutex_siblings, siblings, i);
			if (!added)
			{
				added = true;
				AddFileBack(file);
			}
		}
	}
	if (!added)
	{
		delete mutex_siblings;
		delete siblings;
	}
	return nbPages;
}

int Docapost::IA::Tesseract::MasterProcessingWorker::AddPdfFile(std::string id, char* pdf, int len, std::vector<boost::uuids::uuid>& uids)
{
	MuPDF::MuPDF mupdf;
	auto nbPages = mupdf.GetNbPage(pdf, len);

	std::mutex* mutex_siblings = new std::mutex();
	std::vector<MasterFileStatus*>* siblings = new std::vector<MasterFileStatus*>(nbPages);
	bool added = false;
	for (int i = 0; i < nbPages; i++)
	{
		MasterFileStatus* file = new MasterMemoryFileStatus(id, pdf, len);
		uids.push_back(file->uid);
		InitPdfMasterFileStatus(file, mutex_siblings, siblings, i);
		if (added == false)
		{
			added = true;
			AddFileBack(file);
		}
	}
	return nbPages;
}

void Docapost::IA::Tesseract::MasterProcessingWorker::AddImageFile(bool resume, fs::path path)
{
	bool toProcess = true;
	if (resume)
	{
		toProcess = false;
		if (mOutputTypes & OutputFlags::Text)
		{
			toProcess = toProcess || !FileExist(path);
		}

		if (mOutputTypes & OutputFlags::Metadata)
		{
			toProcess = toProcess || !MetadataExist(path, mOutputTypes & OutputFlags::FastScan);
		}

		if (!toProcess)
		{
			mSkip++;
		}
	}
	if (toProcess)
	{
		mTotal++;
		AddFileBack(new MasterLocalFileStatus(path.string(), fs::relative(path, mInput).string()));
	}
}

void Docapost::IA::Tesseract::MasterProcessingWorker::AddImageFile(std::string id, char* image, int len, boost::uuids::uuid& uuid)
{
	mTotal++;
	MasterMemoryFileStatus* mmfs;
	AddFileBack(mmfs = new MasterMemoryFileStatus(id, image, len));
	uuid = mmfs->uid;
}

void Docapost::IA::Tesseract::MasterProcessingWorker::_AddFolder(fs::path folder, bool resume)
{
	if (!fs::is_directory(folder) || mIsTerminated)
	{
		return;
	}

	for (auto& entry : boost::make_iterator_range(fs::directory_iterator(folder), {}))
	{
		fs::path path = entry.path();
		if (path.filename_is_dot() || path.filename_is_dot_dot())
		{
			continue;
		}
		if (fs::is_directory(path))
		{
			this->_AddFolder(path, resume);
			continue;
		}
		auto ext = path.extension().string();
		if (!extensions.count(ext))
		{
			continue;
		}
		if (ext == ".pdf")
		{
			try
			{

				/*PoDoFo::PdfMemDocument document;
				document.Load(path.string().c_str());
				//PoDoFo::PdfStreamedDocument document(path.string().c_str());
				auto nbPages = document.GetPageCount();*/

				AddPdfFile(resume, path);
			}
			catch (...)
			{
				auto n = GET_EXCEPTION_NAME;
				//BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Impossible de decoder le fichier, le fichier ne sera pas inclue pour traitement " << path.string() << " | " << n;
				std::cerr << "Impossible de decoder le fichier, le fichier ne sera pas inclue pour traitement " << path.string() << " | " << n << std::endl;
			}
		}
		else
		{
			AddImageFile(resume, path);
		}
	}
}
void Docapost::IA::Tesseract::MasterProcessingWorker::AddFolder(fs::path folder, bool resume)
{
	mListingThread = new std::thread([this, folder, resume]()
	{
		CatchAllErrorSignals();
		if (mFiles.size() > 0)
			return;

		mInput = folder;
		_AddFolder(folder, resume);
		mIsEnd = true;

		if (!mIsTerminated)
		{
			mListingThread->detach();
			delete mListingThread;
		}
	});
}

std::thread* Docapost::IA::Tesseract::MasterProcessingWorker::Run(int nbThread)
{
	mStart = boost::posix_time::second_clock::local_time();

	for (const auto& kv : mOutputs) {
		fs::create_directories(kv.second);
	};
	for (int i = 0; i < nbThread; i++)
	{
		AddThread();
	}
	return nullptr;
}
std::string Docapost::IA::Tesseract::MasterProcessingWorker::Compress(std::string& str,
	int compressionlevel = Z_BEST_COMPRESSION)
{
	z_stream zs;                        // z_stream is zlib's control structure
	memset(&zs, 0, sizeof(zs));

	if (deflateInit(&zs, compressionlevel) != Z_OK)
		throw(std::runtime_error("deflateInit failed while compressing."));

	zs.next_in = (Bytef*)str.data();
	zs.avail_in = str.size();           // set the z_stream's input

	int ret;
	char outbuffer[32768];
	std::string outstring;

	// retrieve the compressed bytes blockwise
	do {
		zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
		zs.avail_out = sizeof(outbuffer);

		ret = deflate(&zs, Z_FINISH);

		if (outstring.size() < zs.total_out) {
			// append the block to the output string
			outstring.append(outbuffer,
				zs.total_out - outstring.size());
		}
	} while (ret == Z_OK);

	deflateEnd(&zs);

	if (ret != Z_STREAM_END) {          // an error occurred that was not EOF
		std::ostringstream oss;
		oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
		throw(std::runtime_error(oss.str()));
	}

	return outstring;
}

void Docapost::IA::Tesseract::MasterProcessingWorker::CreateOutput(MasterFileStatus* _file)
{
	if (_file == nullptr)
		return;

	if (_file->result->size() == 0)
		return;

	if (mOutputTypes & OutputFlags::Text && std::find(_file->capability.begin(), _file->capability.end(), OutputFlags::Text) != _file->capability.end())
	{
		// We write the file if we are in file configuration, else the result is already in memory
		if (MasterLocalFileStatus* file = dynamic_cast<MasterLocalFileStatus*>(_file))
		{
			auto ext = mOcrFactory.GetTextExtension();

			for (int i = 0; i < file->result->size(); i++)
			{
				fs::path new_path = ConstructNewTextFilePath(file->new_name, ext[i]);

				fs::create_directories(new_path.parent_path());

				std::ofstream output;
				output.open(new_path.string(), std::ofstream::trunc | std::ofstream::out);
				output << (*file->result)[i];
				output.close();

				//if (i == 0)
				//{
				file->output.push_back(new_path.string());
				file->relative_output.push_back(file->relative_name);
				//}
			}
		}
	}

	if (mOutputTypes & OutputFlags::MemoryImage || mOutputTypes & OutputFlags::Metadata)
	{
		Exiv2::ExifData exifData;

		try
		{
			SXMPMeta meta;
			auto io = new MemoryXMPIO(_file->buffer);
			SXMPFiles xmpfile;
			xmpfile.OpenFile((XMP_IO*)io, kXMP_UnknownFile, kXMPFiles_OpenForUpdate | kXMPFiles_OpenUseSmartHandler);
			auto res = xmpfile.GetXMP(&meta);

			std::string ns;
			SXMPMeta::RegisterNamespace(kXMP_NS_OCRAUTOMATOR, "OcrAutomator", &ns);
			SXMPMeta::RegisterNamespace(kXMP_NS_OCRAUTOMATOR_OCR, "Ocr", &ns);

			auto ocrName = mOcrFactory.Name();

			meta.SetStructField(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, "Outputs", 0, kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered);
			std::string path;
			SXMPUtils::ComposeStructFieldPath(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, "Outputs", &path);

			if (!meta.DoesPropertyExist(kXMP_NS_OCRAUTOMATOR, "Sections"))
			{
				meta.SetProperty(kXMP_NS_OCRAUTOMATOR, "Sections", 0, kXMP_PropValueIsArray);
			}

			if (!meta.DoesPropertyExist(kXMP_NS_OCRAUTOMATOR, ocrName.c_str()))
			{
				meta.AppendArrayItem(kXMP_NS_OCRAUTOMATOR, "Sections", 0, ocrName.c_str(), 0);
			}
			else
			{
				int nbSections = meta.CountArrayItems(kXMP_NS_OCRAUTOMATOR, "Sections");
				bool sectionExist = false;
				for (int i = 0; i < nbSections; i++)
				{
					std::string section;
					meta.GetArrayItem(kXMP_NS_OCRAUTOMATOR, "Sections", i + 1, &section, 0);
					if (section == ocrName)
					{
						sectionExist = true;
						break;
					}
				}
				if (!sectionExist)
				{
					meta.AppendArrayItem(kXMP_NS_OCRAUTOMATOR, "Sections", 0, ocrName.c_str(), 0);
				}
				// if the file already has this OCR output, delete, en rewrite it
				meta.DeleteProperty(kXMP_NS_OCRAUTOMATOR, path.c_str());
				meta.SetStructField(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, "Outputs", 0, kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered);
			}

			for (int i = 0; i < _file->result->size(); i++)
			{
				meta.AppendArrayItem(kXMP_NS_OCRAUTOMATOR, path.c_str(), 0, (*_file->result)[i], 0);
			}
			meta.SetStructField(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, "EngineName", mOcrFactory.Name());
			meta.SetStructField(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, "EngineVersion", mOcrFactory.Version());
			meta.SetStructField(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, "Version", VERSION);

			for (auto& externalProp : mExternalXmp)
			{
				meta.SetStructField(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, externalProp.first.c_str(), externalProp.second);
			}

			auto t = std::time(nullptr);
			auto tm = *std::localtime(&t);
			std::ostringstream oss;
			oss << std::put_time(&tm, "%Y-%m-%dT%H:%M:%S%z");
			auto str = oss.str();

			meta.SetStructField(kXMP_NS_OCRAUTOMATOR, ocrName.c_str(), kXMP_NS_OCRAUTOMATOR_OCR, "Date", str.c_str());
			xmpfile.PutXMP(meta);
			xmpfile.CloseFile();
			_file->buffer = io->Buffer();
			delete io;
		}
		catch (XMP_Error& wmp_err)
		{
			BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "cannot Write XMP : " << wmp_err.GetErrMsg();
		}
	}

	if (mOutputTypes & OutputFlags::Metadata && std::find(_file->capability.begin(), _file->capability.end(), OutputFlags::Metadata) != _file->capability.end())
	{
		if (MasterLocalFileStatus* file = dynamic_cast<MasterLocalFileStatus*>(_file))
		{
			fs::path new_path = ConstructNewExifFilePath(file->new_name);
			auto it = mOutputs.find(OutputFlags::Metadata);
			if (it != mOutputs.end() && it->second != mInput)
			{
				fs::create_directories(new_path.parent_path());
				if (fs::exists(new_path))
				{
					fs::remove(new_path);
				}
			}
			std::ofstream stream(new_path.string(), std::ios_base::out | std::ios_base::binary);
			stream.write((char*)file->buffer->data(), file->buffer->len());

			file->output.push_back(new_path.string());
			file->relative_output.push_back(file->relative_name);
		}
	}
}

void Docapost::IA::Tesseract::MasterProcessingWorker::FreeBuffers(MasterFileStatus* file, bool memoryImage, bool memoryText, bool canDeleteText)
{
	if (file->buffer == nullptr)
		return;

	if (!memoryImage)
	{
		delete file->buffer;
		file->buffer = nullptr;
	}

	if (!memoryText && canDeleteText)
	{
		if (file->filePosition >= 0)
		{
			for (int i = 0; i < file->siblings->size(); i++)
			{
				auto item = (*file->siblings)[i];
				if (item != nullptr)
				{
					if (item->isCompleted)
					{
						item->result.reset();
						break;
					}
				}
			}
		}
		else
		{
			file->result.reset();
		}
	}
}

void Docapost::IA::Tesseract::MasterProcessingWorker::ThreadLoop(int id)
{
	CatchAllErrorSignals();

	Ocr* ocr = nullptr;
	try
	{
		ocr = mOcrFactory.CreateNew();
		ocr->InitEngine();
	}
	catch (UninitializedOcrException& e)
	{
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::error) << "Thread " << id << " - " << e.message();
		return;
	}

	while (ocr != nullptr && !mIsTerminated)
	{
		try
		{
			MasterFileStatus * file = GetFile();
			if (file == nullptr)
			{
				{
					boost::lock_guard<std::mutex> lock(mThreadMutex);
					if (mNbThreadToStop > 0)
					{
						--mNbThreadToStop;
						//mThreads.erase(id);

						break;
					}
				}
				if (mDone == mTotal && mFileSend.empty() && mIsEnd)
				{
					break;
				}
				std::this_thread::sleep_for(std::chrono::milliseconds(300));
				continue;
			}

			file->uuid = boost::uuids::uuid();
			file->thread = id;
			file->start = boost::posix_time::microsec_clock::local_time();

			if (file->abandoned)
			{
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Exclude file " << file->name << ":" << file->filePosition;
				Log::WriteFileToExclude(file);
				mDone++;
				file->end = boost::posix_time::microsec_clock::local_time();
				file->ellapsed = file->end - file->start;
				file->isEnd = true;
				continue;
			}

			try
			{
				// If we got null, it meen that the processing is in progress, just wait, otherwise the file is usable, just use it
				if (nullptr == ocr->LoadFile(file, boost::bind(&MasterProcessingWorker::AddFile, this, _1)))
				{
					BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "LoadFile null waiting 1000ms";
					std::this_thread::sleep_for(std::chrono::milliseconds(1000));
					continue;
				}
			}
			catch (std::runtime_error& e)
			{
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Cannot load file";
				if (file->retry < MAX_RETRY)
				{
					file->retry++;
					AddFileBack(file);
				}
				else
				{
					Log::WriteFileToExclude(file);
				}
				continue;
			}
			onStartProcessFile(file);

			try
			{
				file->result = ocr->ProcessThroughOcr(file->buffer);
				if (file->result->empty())
				{
					if (file->retry < MAX_RETRY)
					{
						file->retry++;
						AddFileBack(file);
					}
					else
					{
						Log::WriteFileToExclude(file);
					}
					continue;
				}
			}
			catch (std::runtime_error& error)
			{
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Error: " << error.what();
				onFileCanceled(file);
				if (file->retry < MAX_RETRY)
				{
					file->retry++;
					AddFileBack(file);
				}
				else
				{
					Log::WriteFileToExclude(file);
				}
				continue;
			}

			try
			{
				CreateOutput(file);
			}
			catch (std::exception& e)
			{
				BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Cannot write output: " << e.what();
				onFileCanceled(file);
				if (file->retry < MAX_RETRY)
				{
					Log::WriteFileToExclude(file);
					file->retry++;
					AddFileBack(file);
				}
				continue;
			}

			auto isMerge = MergeResult(file);

			FreeBuffers(file, mOutputTypes & OutputFlags::MemoryImage, (mOutputTypes & OutputFlags::MemoryText), isMerge);

			mDone++;

			file->end = boost::posix_time::microsec_clock::local_time();
			file->ellapsed = file->end - file->start;
			file->isEnd = true;

			onEndProcessFile(file);

			boost::lock_guard<std::mutex> lock(mThreadMutex);
			if (mNbThreadToStop > 0)
			{
				--mNbThreadToStop;
				//mThreads.erase(id);

				break;
			}
		}
		catch (const std::exception& e)
		{
			BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Thread - " << id << " " << e.what();
		}
		catch (...)
		{
			auto n = GET_EXCEPTION_NAME;
			BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Thread - " << id << " | " << n;
		}
	}

	try
	{
		// Destroy Ocr class
		std::cerr << "Thread end api " << id << std::endl;
		delete ocr;
	}
	catch (const std::exception& e)
	{
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Thread - " << id << " " << e.what();
	}
	catch (...)
	{
		auto n = GET_EXCEPTION_NAME;
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Thread - " << id << " | " << n;
	}

	TerminateThread(id);
}

void Docapost::IA::Tesseract::MasterProcessingWorker::TerminateThread(int id)
{
	BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Thread " << id << " begin terminate procedure";

	{
		std::unique_lock<std::mutex> lockManagement(mThreadManagementMutex, std::try_to_lock);
		if (lockManagement.owns_lock())
		{
			BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Thread " << id << " owned, removed from thread list";
			mThreads[id]->detach();
			delete mThreads[id];
		}
		else
		{
			BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Thread " << id << " not owned, removed and delete delegate to caller";
		}
		mThreads.erase(id);
	}

	boost::lock_guard<std::mutex> lock(mThreadMutex);
	if (mThreads.size() == 0)
	{
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Last thread running stopped";
		while (mFileSend.size() > 0)
		{
			BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Wait for " << mFileSend.size() << " file to be retrieved, retry in 300ms";
			std::this_thread::sleep_for(std::chrono::milliseconds(300));
		}
		mEnd = boost::posix_time::second_clock::local_time();
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Stoping network";
		onProcessEnd();

		std::unique_lock<std::mutex> lk(mIsWorkDoneMutex);
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Notify everyone of the shutdown";
		mIsWorkDone.notify_all();
	}

	BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Thread " << id << " terminate";
}

void Docapost::IA::Tesseract::MasterProcessingWorker::SetOutput(boost::unordered_map<OutputFlags, fs::path> folders)
{
	this->mOutputs = folders;
}

Docapost::IA::Tesseract::MasterProcessingWorker::~MasterProcessingWorker()
{
	mIsTerminated = true;
	BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "Destroying MasterProcessingWorker";

	boost::lock_guard<std::mutex> lock(mThreadManagementMutex);
	const auto ths = mThreads;
	for (auto th : ths)
	{
		if (th.second->joinable())
			th.second->join();

		delete th.second;
	}
	BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Stoping network";
	mNetwork->Stop();
	mNetwork.reset();
	BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "network Stop";
	if (mNetworkThread != nullptr)
	{
		BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::trace) << "Waiting for network Thread to complete";
		mNetworkThread->join();
		delete mNetworkThread;
	}
	BOOST_LOG_WITH_LINE(Log::CommonLogger, boost::log::trivial::warning) << "MasterProcessingWorker Destroyed";
}

max_stars_repo_name: labinnovationdocapost/ocrAutomator

max_issues_repo_name: labinnovationdocapost/ocrAutomator

max_forks_repo_name: labinnovationdocapost/ocrAutomator


text:
/** ****************************************************************************
 *  @file    FaceAlignment3dde.cpp
 *  @brief   Face detection and recognition framework
 *  @author  Roberto Valle Fernandez
 *  @date    2018/10
 *  @copyright All rights reserved.
 *  Software developed by UPM PCR Group: http://www.dia.fi.upm.es/~pcr
 ******************************************************************************/

// ----------------------- INCLUDES --------------------------------------------
#include <FaceAlignment3dde.hpp>
#include <trace.hpp>
#include <utils.hpp>
#include <cereal/cereal.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/types/map.hpp>
#include <cereal/types/vector.hpp>
#include <boost/progress.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <fstream>

namespace upm {

const float FACE_HEIGHT = 160.0f;

// -----------------------------------------------------------------------------
//
// Purpose and Method:
// Inputs:
// Outputs:
// Dependencies:
// Restrictions and Caveats:
//
// -----------------------------------------------------------------------------
void
FaceAlignment3dde::parseOptions
  (
  int argc,
  char **argv
  )
{
  /// Declare the supported program options
  FaceAlignment::parseOptions(argc, argv);
  namespace po = boost::program_options;
  po::options_description desc("FaceAlignment3dde options");
  UPM_PRINT(desc);
};

// -----------------------------------------------------------------------------
//
// Purpose and Method:
// Inputs:
// Outputs:
// Dependencies:
// Restrictions and Caveats:
//
// -----------------------------------------------------------------------------
void
FaceAlignment3dde::train
  (
  const std::vector<upm::FaceAnnotation> &anns_train,
  const std::vector<upm::FaceAnnotation> &anns_valid
  )
{
  /// Training ERT model
  UPM_PRINT("Training ERT will be released soon ...");
};

// -----------------------------------------------------------------------------
//
// Purpose and Method:
// Inputs:
// Outputs:
// Dependencies:
// Restrictions and Caveats:
//
// -----------------------------------------------------------------------------
void
FaceAlignment3dde::load()
{
  /// Loading shape predictors
  UPM_PRINT("Loading facial-feature predictors");
  std::vector<std::string> paths;
  boost::filesystem::path dir_path(_path + _database + "/");
  boost::filesystem::directory_iterator end_it;
  for (boost::filesystem::directory_iterator it(dir_path); it != end_it; ++it)
    paths.push_back(it->path().string());
  sort(paths.begin(), paths.end());
  UPM_PRINT("> Number of predictors found: " << paths.size());

  _sp.resize(HP_LABELS.size());
  for (const std::string &path : paths)
  {
    try
    {
      std::ifstream ifs(path);
      cereal::BinaryInputArchive ia(ifs);
      ia >> _sp[boost::lexical_cast<unsigned int>(path.substr(0,path.size()-4).substr(path.find_last_of('_')+1))] >> DB_PARTS >> DB_LANDMARKS;
      ifs.close();
    }
    catch (cereal::Exception &ex)
    {
      UPM_ERROR("Exception during predictor deserialization: " << ex.what());
    }
  }
};

// -----------------------------------------------------------------------------
//
// Purpose and Method:
// Inputs:
// Outputs:
// Dependencies:
// Restrictions and Caveats:
//
// -----------------------------------------------------------------------------
void
FaceAlignment3dde::process
  (
  cv::Mat frame,
  std::vector<FaceAnnotation> &faces,
  const FaceAnnotation &ann
  )
{
  /// Analyze each detected face to tell us the face part locations
  for (FaceAnnotation &face : faces)
  {
    int yaw_idx = getHeadposeIdx(FaceAnnotation().headpose.x);
    cv::Mat img;
    float scale = FACE_HEIGHT/face.bbox.pos.height;
    cv::resize(frame, img, cv::Size(), scale, scale);
    _sp[yaw_idx].process(img, scale, face, ann, _measure, _path);
  }
};

} // namespace upm

ext: cpp


text:
#include <Eigen/Eigen>
#include <iostream>

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif

using namespace Eigen;
using namespace std;

int main(int, char**)
{
  cout.precision(3);
  SelfAdjointEigenSolver<Matrix4f> es;
Matrix4f X = Matrix4f::Random(4,4);
Matrix4f A = X + X.transpose();
es.compute(A);
cout << "The eigenvalues of A are: " << es.eigenvalues().transpose() << endl;
es.compute(A + Matrix4f::Identity(4,4)); // re-use es to compute eigenvalues of A+I
cout << "The eigenvalues of A+I are: " << es.eigenvalues().transpose() << endl;

  return 0;
}


text:
#include <boost/python.hpp>
#include "myextension.hpp"

using namespace boost::python;

BOOST_PYTHON_MODULE(myextension)
{
    class_<Base>("Base", init<std::string>())
        .def("__str__", &Base::name)
    ;

}

max_stars_repo_name: SafinaM/boost-python-examples

max_issues_repo_name: SafinaM/boost-python-examples

max_forks_repo_name: SafinaM/boost-python-examples


text:
// ------------------------------------------------------------------
// pion-net: a C++ framework for building lightweight HTTP interfaces
// ------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#include <sstream>
#include <vector>
#include <algorithm>
#include <pion/PionConfig.hpp>
#include <pion/net/HTTPMessage.hpp>
#include <pion/net/HTTPRequest.hpp>
#include <pion/net/HTTPResponse.hpp>
#include <pion/PionUnitTestDefs.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/mpl/list.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/foreach.hpp>

using namespace pion::net;

BOOST_AUTO_TEST_CASE(checkHTTPRequestCopyConstructor) {
	HTTPRequest req1;
	req1.addHeader("Test", "HTTPMessage");
	req1.setMethod("GET");
	HTTPRequest req2(req1);
	BOOST_CHECK_EQUAL(req1.getMethod(), "GET");
	BOOST_CHECK_EQUAL(req1.getMethod(), req2.getMethod());
	BOOST_CHECK_EQUAL(req1.getHeader("Test"), "HTTPMessage");
	BOOST_CHECK_EQUAL(req1.getHeader("Test"), req2.getHeader("Test"));
}

BOOST_AUTO_TEST_CASE(checkHTTPRequestAssignmentOperator) {
	HTTPRequest req1, req2;
	req1.setMethod("GET");
	req1.addHeader("Test", "HTTPMessage");
	req2 = req1;
	BOOST_CHECK_EQUAL(req1.getMethod(), "GET");
	BOOST_CHECK_EQUAL(req1.getMethod(), req2.getMethod());
	BOOST_CHECK_EQUAL(req1.getHeader("Test"), "HTTPMessage");
	BOOST_CHECK_EQUAL(req1.getHeader("Test"), req2.getHeader("Test"));
}

BOOST_AUTO_TEST_CASE(checkHTTPResponseCopyConstructor) {
	HTTPResponse rsp1;
	rsp1.addHeader("Test", "HTTPMessage");
	rsp1.setStatusCode(199);
	HTTPResponse rsp2(rsp1);
	BOOST_CHECK_EQUAL(rsp1.getStatusCode(), 199U);
	BOOST_CHECK_EQUAL(rsp1.getStatusCode(), rsp2.getStatusCode());
	BOOST_CHECK_EQUAL(rsp1.getHeader("Test"), "HTTPMessage");
	BOOST_CHECK_EQUAL(rsp1.getHeader("Test"), rsp2.getHeader("Test"));
}

BOOST_AUTO_TEST_CASE(checkHTTPResponseAssignmentOperator) {
	HTTPResponse rsp1, rsp2;
	rsp1.addHeader("Test", "HTTPMessage");
	rsp1.setStatusCode(199);
	rsp2 = rsp1;
	BOOST_CHECK_EQUAL(rsp1.getStatusCode(), 199U);
	BOOST_CHECK_EQUAL(rsp1.getStatusCode(), rsp2.getStatusCode());
	BOOST_CHECK_EQUAL(rsp1.getHeader("Test"), "HTTPMessage");
	BOOST_CHECK_EQUAL(rsp1.getHeader("Test"), rsp2.getHeader("Test"));
}

BOOST_AUTO_TEST_CASE(checkGetFirstLineForRequest) {
	HTTPRequest http_request;

	http_request.setMethod("GET");
	http_request.setResource("/");

	BOOST_CHECK_EQUAL(http_request.getFirstLine(), "GET / HTTP/1.1");

	http_request.setMethod("POST");

	BOOST_CHECK_EQUAL(http_request.getFirstLine(), "POST / HTTP/1.1");

	http_request.setResource("/index.html");

	BOOST_CHECK_EQUAL(http_request.getFirstLine(), "POST /index.html HTTP/1.1");

	http_request.setVersionMajor(1);
	http_request.setVersionMinor(0);

	BOOST_CHECK_EQUAL(http_request.getFirstLine(), "POST /index.html HTTP/1.0");
}

BOOST_AUTO_TEST_CASE(checkGetFirstLineForResponse) {
	HTTPResponse http_response;

	http_response.setStatusCode(HTTPTypes::RESPONSE_CODE_OK);
	http_response.setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_OK);

	BOOST_CHECK_EQUAL(http_response.getFirstLine(), "HTTP/1.1 200 OK");

	http_response.setStatusCode(HTTPTypes::RESPONSE_CODE_NOT_FOUND);

	BOOST_CHECK_EQUAL(http_response.getFirstLine(), "HTTP/1.1 404 OK");

	http_response.setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NOT_FOUND);

	BOOST_CHECK_EQUAL(http_response.getFirstLine(), "HTTP/1.1 404 Not Found");
}

#define FIXTURE_TYPE_LIST(F) boost::mpl::list<F<HTTPRequest>, F<HTTPResponse> >

template<typename ConcreteMessageType>
class NewHTTPMessage_F : public ConcreteMessageType {
public:
	NewHTTPMessage_F() {
	}
	~NewHTTPMessage_F() {
	}
};

BOOST_AUTO_TEST_SUITE_FIXTURE_TEMPLATE(NewHTTPMessage_S,
									   FIXTURE_TYPE_LIST(NewHTTPMessage_F))

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentLengthReturnsZero) {
	BOOST_CHECK_EQUAL(F::getContentLength(), static_cast<size_t>(0));
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkSetContentLengthDoesntThrow) {
	BOOST_CHECK_NO_THROW(F::setContentLength(10));
	BOOST_CHECK_NO_THROW(F::setContentLength(0));
}

// Is this what we want?  Note that the length is zero here.
BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkCreateContentBufferReturnsPointer) {
	BOOST_CHECK(F::createContentBuffer() != NULL);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsEmptyString) {
	BOOST_CHECK(F::getContent() != NULL);
	BOOST_CHECK_EQUAL(strcmp(F::getContent(), ""), 0);
	BOOST_CHECK(!F::isContentBufferAllocated());
}

// Is this what we want?  Note that the length is zero here.
BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsPointerAfterCreatingContentBuffer) {
	F::createContentBuffer();
	BOOST_CHECK(F::getContent() != NULL);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkIsValidReturnsFalse) {
	BOOST_CHECK(!F::isValid());
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(testChunksSupportedAccessors) {
	BOOST_CHECK(!F::getChunksSupported());
	F::setChunksSupported(true);
	BOOST_CHECK(F::getChunksSupported());
	F::setChunksSupported(false);
	BOOST_CHECK(!F::getChunksSupported());
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(testHeaderCaseIsIgnored) {
	const std::string xml_content_type("text/xml");

	F::addHeader(HTTPTypes::HEADER_CONTENT_TYPE, xml_content_type);
	BOOST_CHECK_EQUAL(F::getHeader("CoNTenT-TYPe"), xml_content_type);

	F::addHeader("content-length", "10");
	BOOST_CHECK_EQUAL(F::getHeader(HTTPTypes::HEADER_CONTENT_LENGTH), "10");
}

BOOST_AUTO_TEST_SUITE_END()

template<typename ConcreteMessageType>
class HTTPMessageWithContentLengthSet_F : public ConcreteMessageType {
public:
	HTTPMessageWithContentLengthSet_F() {
		this->setContentLength(20);
	}
	~HTTPMessageWithContentLengthSet_F() {
	}
};

BOOST_AUTO_TEST_SUITE_FIXTURE_TEMPLATE(HTTPMessageWithContentLengthSet_S,
									   FIXTURE_TYPE_LIST(HTTPMessageWithContentLengthSet_F))

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentLengthReturnsCorrectLength) {
	BOOST_CHECK_EQUAL(F::getContentLength(), static_cast<size_t>(20));
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentLengthAfterSettingLengthAgain) {
	F::setContentLength(30);
	BOOST_CHECK_EQUAL(F::getContentLength(), static_cast<size_t>(30));
	F::setContentLength(0);
	BOOST_CHECK_EQUAL(F::getContentLength(), static_cast<size_t>(0));
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkCreateContentBufferVarious) {
	char *ptr = F::createContentBuffer();
	BOOST_CHECK(ptr != NULL);
	BOOST_CHECK_EQUAL(ptr, F::getContent());
	BOOST_CHECK_EQUAL(F::getContentBufferSize(), 20);
	BOOST_CHECK(F::isContentBufferAllocated());
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsEmptyString) {
	BOOST_CHECK(F::getContent() != NULL);
	BOOST_CHECK_EQUAL(strcmp(F::getContent(), ""), 0);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkIsValidReturnsFalse) {
	BOOST_CHECK(!F::isValid());
}

BOOST_AUTO_TEST_SUITE_END()

template<typename ConcreteMessageType>
class HTTPMessageWithContentBufferCreated_F : public ConcreteMessageType {
public:
	HTTPMessageWithContentBufferCreated_F() {
		m_len = 10;
		this->setContentLength(m_len);
		m_content_buffer = this->createContentBuffer();
	}
	~HTTPMessageWithContentBufferCreated_F() {
	}

	int m_len;
	char* m_content_buffer;
};

BOOST_AUTO_TEST_SUITE_FIXTURE_TEMPLATE(HTTPMessageWithContentBufferCreated_S,
									   FIXTURE_TYPE_LIST(HTTPMessageWithContentBufferCreated_F))

// ???
BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkCreateContentBufferAgainReturnsPointer) {
	BOOST_CHECK(F::createContentBuffer() != NULL);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsPointer) {
	BOOST_CHECK(F::getContent() != NULL);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsWhatWasWrittenToBuffer) {
	char buf[] = {0, 1, 2, 3, 127, 0, -1, -2, -3, -128};
	BOOST_CHECK_EQUAL(sizeof(buf), static_cast<unsigned int>(F::m_len));
	memcpy(F::m_content_buffer, buf, F::m_len);
	BOOST_CHECK(memcmp(buf, F::getContent(), F::m_len) == 0);
}

BOOST_AUTO_TEST_SUITE_END()

static const char TEXT_STRING_1[] = "0123456789";
static const char TEXT_STRING_2[] = "9876543210";
static const char TEXT_STRING_3[] = "0123456789abcde";

template<typename ConcreteMessageType>
class HTTPMessageWithTextOnlyContent_F : public ConcreteMessageType {
public:
	HTTPMessageWithTextOnlyContent_F() {
		m_len = strlen(TEXT_STRING_1);
		this->setContentLength(m_len);
		m_content_buffer = this->createContentBuffer();
		memcpy(m_content_buffer, TEXT_STRING_1, m_len);
	}
	~HTTPMessageWithTextOnlyContent_F() {
	}

	size_t m_len;
	char* m_content_buffer;
};

BOOST_AUTO_TEST_SUITE_FIXTURE_TEMPLATE(HTTPMessageWithTextOnlyContent_S,
									   FIXTURE_TYPE_LIST(HTTPMessageWithTextOnlyContent_F))

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsPointer) {
	BOOST_CHECK(F::getContent() != NULL);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsWhatWasWrittenToBuffer) {
	BOOST_CHECK(memcmp(TEXT_STRING_1, F::getContent(), F::m_len) == 0);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentAfterChangingContent) {
	BOOST_CHECK_EQUAL(strlen(TEXT_STRING_2), static_cast<unsigned int>(F::m_len));
	memcpy(F::m_content_buffer, TEXT_STRING_2, F::m_len);
	BOOST_CHECK(memcmp(TEXT_STRING_2, F::getContent(), F::m_len) == 0);
}

BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentAfterChangingSizeAndContent) {
	F::m_len = strlen(TEXT_STRING_3);
	F::setContentLength(F::m_len);
	F::m_content_buffer = F::createContentBuffer();
	memcpy(F::m_content_buffer, TEXT_STRING_3, F::m_len);
	BOOST_CHECK(memcmp(TEXT_STRING_3, F::getContent(), F::m_len) == 0);
}

// This is just for convenience for text-only post content.
// Strictly speaking, getContent() guarantees nothing beyond the buffer.
BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkGetContentReturnsZeroTerminatedBuffer) {
	// This crashes due to bug in Boost.Test if m_content_buffer[m_len] is negative, so use workaround.
	//BOOST_CHECK_EQUAL(m_content_buffer[m_len], static_cast<char>(0));

	// Illustration of bug:
	//char c1 = -2;
	//char c2 = -2;
	//BOOST_CHECK_EQUAL(c1, c2);

	BOOST_CHECK_EQUAL(static_cast<int>(F::m_content_buffer[F::m_len]), static_cast<int>(0));
}

// See comments for checkGetContentReturnsZeroTerminatedBuffer.
BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(checkContentPointerUsableAsString) {
	const std::string s1 = TEXT_STRING_1;
	std::string s2 = F::getContent();
	BOOST_CHECK_EQUAL(s1, s2);
}

BOOST_AUTO_TEST_SUITE_END()

/// simple fixture for testing read() and write() methods
class HTTPMessageReadWrite_F {
public:
	HTTPMessageReadWrite_F()
		: m_filename("output.tmp")
	{
		openNewFile();
	}

	~HTTPMessageReadWrite_F() {
		m_file.close();
		boost::filesystem::remove(m_filename);
	}

	void openNewFile(void) {
		if (m_file.is_open()) {
			m_file.close();
			m_file.clear();
		}
		m_file.open(m_filename.c_str(), std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
		BOOST_REQUIRE(m_file.is_open());
	}

	std::string getFileContents(void) {
		// if only it were this easy... unfortunately order of headers can vary
		//std::stringstream ss;
		//m_file.seekg(0);
		//ss << m_file.rdbuf();
		//return ss.str();

		char line[256];
		std::stringstream ss;
		std::vector<std::string> lines;
		bool is_first_line = true;

		m_file.clear();
		m_file.seekg(0);

		while (m_file.getline(line, 255)) {
			std::size_t len = strlen(line);
			if (len > 0 && line[len-1]=='\r')
				line[len-1] = '\0';
			if (is_first_line) {
				ss << line << "\r\n";
				lines.clear();
				is_first_line = false;
			} else if (line[0] == '\0') {
				std::sort(lines.begin(), lines.end());
				BOOST_FOREACH(const std::string& l, lines) {
					ss << l << "\r\n";
				}
				ss << "\r\n";
				lines.clear();
				is_first_line = true;
			} else {
				lines.push_back(line);
			}
		}

		std::sort(lines.begin(), lines.end());
		BOOST_FOREACH(const std::string& l, lines) {
			ss << l << "\r\n";
		}

		return ss.str();
	}

	std::string		m_filename;
	std::fstream	m_file;
};

BOOST_FIXTURE_TEST_SUITE(HTTPMessageReadWrite_S, HTTPMessageReadWrite_F)

BOOST_AUTO_TEST_CASE(checkWriteReadHTTPRequestNoContent) {
	// build a request
	HTTPRequest req;
	req.setResource("/test.html");
	req.addHeader("Test", "Something");

	// write to file
	boost::system::error_code ec;
	req.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	m_file.flush();

	// read from file
	HTTPRequest req2;
	m_file.clear();
	m_file.seekg(0);
	req2.read(m_file, ec);
	BOOST_REQUIRE(! ec);

	// make sure we're now at EOF
	HTTPRequest req3;
	req3.read(m_file, ec);
	BOOST_CHECK_EQUAL(ec, boost::system::errc::io_error);

	// check request read from file
	BOOST_CHECK_EQUAL(req2.getResource(), "/test.html");
	BOOST_CHECK_EQUAL(req2.getHeader("Test"), "Something");
	BOOST_CHECK_EQUAL(req2.getContentLength(), 0U);

	// validate file contents
	std::string req_contents = getFileContents();
	BOOST_CHECK_EQUAL(req_contents, "GET /test.html HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\nTest: Something\r\n\r\n");

	// create a new file for req2
	openNewFile();
	req2.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	m_file.flush();

	// make sure file matches original (no loss/change from read/write cycle)
	std::string req2_contents = getFileContents();
	BOOST_CHECK_EQUAL(req_contents, req2_contents);
}

BOOST_AUTO_TEST_CASE(checkWriteReadHTTPResponseNoContent) {
	// build a response
	HTTPResponse rsp;
	rsp.setStatusCode(202);
	rsp.setStatusMessage("Hi There");
	rsp.addHeader("HeaderA", "a value");

	// write to file
	boost::system::error_code ec;
	rsp.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	m_file.flush();

	// read from file
	HTTPResponse rsp2;
	m_file.clear();
	m_file.seekg(0);
	rsp2.read(m_file, ec);
	BOOST_REQUIRE(! ec);

	// make sure we're now at EOF
	HTTPResponse rsp3;
	rsp3.read(m_file, ec);
	BOOST_CHECK_EQUAL(ec, boost::system::errc::io_error);

	// check response read from file
	BOOST_CHECK_EQUAL(rsp2.getStatusCode(), 202U);
	BOOST_CHECK_EQUAL(rsp2.getStatusMessage(), "Hi There");
	BOOST_CHECK_EQUAL(rsp2.getHeader("HeaderA"), "a value");
	BOOST_CHECK_EQUAL(rsp2.getContentLength(), 0U);

	// validate file contents
	std::string rsp_contents = getFileContents();
	BOOST_CHECK_EQUAL(rsp_contents, "HTTP/1.1 202 Hi There\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\nHeaderA: a value\r\n\r\n");

	// create a new file for rsp2
	openNewFile();
	rsp2.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	m_file.flush();

	// make sure file matches original (no loss/change from read/write cycle)
	std::string rsp2_contents = getFileContents();
	BOOST_CHECK_EQUAL(rsp_contents, rsp2_contents);
}

BOOST_AUTO_TEST_CASE(checkWriteReadMixedMessages) {
	boost::system::error_code ec;
	HTTPRequest req;
	HTTPResponse rsp;

	// build a request & write to file
	req.setResource("/test.html");
	req.addHeader("Test", "Something");
	req.write(m_file, ec);
	BOOST_REQUIRE(! ec);

	// build a response & write to file
	rsp.setStatusCode(202);
	rsp.setStatusMessage("Hi There");
	rsp.addHeader("HeaderA", "a value");
	rsp.setContent("My message content");
	rsp.write(m_file, ec);
	BOOST_REQUIRE(! ec);

	// another request
	req.setResource("/blah.html");
	req.addHeader("HeaderA", "a value");
	req.setContent("My request content");
	req.write(m_file, ec);
	BOOST_REQUIRE(! ec);

	// another response
	rsp.setStatusCode(302);
	rsp.setStatusMessage("Hello There");
	rsp.addHeader("HeaderB", "another value");
	rsp.clearContent();
	rsp.write(m_file, ec);
	BOOST_REQUIRE(! ec);

	// one last request
	req.setResource("/last.html");
	req.addHeader("HeaderB", "Bvalue");
	req.clearContent();
	req.write(m_file, ec);
	BOOST_REQUIRE(! ec);

	// flush file output
	m_file.flush();

	// validate file contents
	std::string contents = getFileContents();
	BOOST_CHECK_EQUAL(contents, "GET /test.html HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\nTest: Something\r\n\r\n"
		"HTTP/1.1 202 Hi There\r\nConnection: Keep-Alive\r\nContent-Length: 18\r\nHeaderA: a value\r\n\r\nMy message content"
		"GET /blah.html HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 18\r\nHeaderA: a value\r\nTest: Something\r\n\r\nMy request content"
		"HTTP/1.1 302 Hello There\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\nHeaderA: a value\r\nHeaderB: another value\r\n\r\n"
		"GET /last.html HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\nHeaderA: a value\r\nHeaderB: Bvalue\r\nTest: Something\r\n\r\n");

	m_file.clear();
	m_file.seekg(0);

	// read first request
	HTTPRequest req1;
	req1.read(m_file, ec);
	BOOST_REQUIRE(! ec);

	// read first response
	HTTPResponse rsp1;
	rsp1.read(m_file, ec);
	BOOST_REQUIRE(! ec);

	// read second request
	HTTPRequest req2;
	req2.read(m_file, ec);
	BOOST_REQUIRE(! ec);

	// read second response
	HTTPResponse rsp2;
	rsp2.read(m_file, ec);
	BOOST_REQUIRE(! ec);
	BOOST_CHECK_EQUAL(rsp2.getStatusCode(), 302U);
	BOOST_CHECK_EQUAL(rsp2.getStatusMessage(), "Hello There");

	// read third request
	HTTPRequest req3;
	req3.read(m_file, ec);
	BOOST_REQUIRE(! ec);

	// write everything back to new file
	openNewFile();
	req1.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	rsp1.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	req2.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	rsp2.write(m_file, ec);
	BOOST_REQUIRE(! ec);
	req3.write(m_file, ec);
	BOOST_REQUIRE(! ec);

	// flush file output
	m_file.flush();

	// make sure file matches original (no loss/change from read/write cycle)
	std::string new_contents = getFileContents();
	BOOST_CHECK_EQUAL(contents, new_contents);
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: marshallmcmullen/pion

max_issues_repo_name: marshallmcmullen/pion

max_forks_repo_name: marshallmcmullen/pion


text:
#include "config.h"

#include "host_condition.hpp"

#include <boost/algorithm/string.hpp>
#include <sdbusplus/bus.hpp>

#include <cstdlib>
#include <iostream>

int main(int argc, char** argv)
{
    std::string hostId;

    if (argc == 2)
    {
        hostId = std::string(argv[1]);
    }
    else
    {
        return 0;
    }

    auto bus = sdbusplus::bus::new_default();
    std::string objGroupName = HOST_GPIOS_OBJPATH;
    std::string objPathInst = objGroupName + "/host" + hostId;
    std::string busName = HOST_GPIOS_BUSNAME;

    // Add sdbusplus ObjectManager
    sdbusplus::server::manager::manager objManager(bus, objGroupName.c_str());

    // For now, we only support checking Host0 status
    auto host = std::make_unique<phosphor::condition::Host>(
        bus, objPathInst.c_str(), hostId);

    bus.request_name(busName.c_str());

    while (true)
    {
        bus.process_discard();
        bus.wait();
    }

    return 0;
}

max_stars_repo_name: msbarth/ibm-phosphor-state-manager

max_issues_repo_name: msbarth/ibm-phosphor-state-manager

max_forks_repo_name: msbarth/ibm-phosphor-state-manager


text:
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>

void wait(int seconds)
{
  boost::this_thread::sleep_for(boost::chrono::seconds{seconds});
}

void thread()
{
  for (int i = 0; i < 5; ++i)
  {
    wait(1);
    std::cout << "1st thread \n";
    std::cout << i << '\n';
  }
}

void thread2()
{
  for (int i = 0; i < 5; ++i)
  {
    wait(1);
    std::cout << "2st thread \n";
    std::cout << i << '\n';
  }
}

int main()
{
  boost::thread t{thread};
  boost::thread t2{thread2};

  for (int i = 0; i < 5; ++i)
  {
    wait(1);
    std::cout << "main thread \n";
    std::cout << i << '\n';
  }
  t.join();
  t2.join();
}


text:
/*
   Copyright (C) 2015-2021 by Synge Todo <wistaria@phys.s.u-tokyo.ac.jp>

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

// Ground state energy of the transverse Ising chain

#include <iomanip>
#include <iostream>
#include <string>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include "options.hpp"
#include "chain.hpp"
#include "convert.hpp"

template<typename T>
void calc(const options& opt) {
  using namespace tfi::energy;
  using std::abs;
  typedef T real_t;
  real_t J = convert<real_t>(opt.J);
  real_t GammaMin, GammaMax, dGamma;
  if (opt.GammaMin == "GammaC") {
    GammaMin = GammaMax = dGamma = abs(J);
  } else {
    GammaMin = convert<real_t>(opt.GammaMin);
    GammaMax = convert<real_t>(opt.GammaMax);
    dGamma = convert<real_t>(opt.dGamma);
  }
  // if (Tmin < 0 || Tmax < 0) throw(std::invalid_argument("Temperature should be positive"));
  // if (GammaMin > GammaMax) throw(std::invalid_argument("GammaMax should be larger than GammaMin"));
  // if (dGamma <= 0) throw(std::invalid_argument("dGamma should be positive"));
  std::cout << std::scientific << std::setprecision(std::numeric_limits<real_t>::digits10)
            << "# lattice: chain\n"
            << "# precision: " << std::numeric_limits<real_t>::digits10 << std::endl
            << "# L J Gamma E/L\n";
  for (auto Gamma = GammaMin; Gamma < GammaMax + 1e-4 * dGamma; Gamma += dGamma) {
    auto ene = chain::infinite(J, Gamma);
    std::cout << "inf " << J << ' ' << Gamma << ' ' << ene << std::endl;
  }
}

int main(int argc, char **argv) {
  using namespace boost::multiprecision;
  options opt(argc, argv);
  if (!opt.valid) return 127;
  if (opt.prec <= std::numeric_limits<float>::digits10) {
    calc<float>(opt);
  } else if (opt.prec <= std::numeric_limits<double>::digits10) {
    calc<double>(opt);
  } else if (opt.prec <= std::numeric_limits<cpp_dec_float_50>::digits10) {
    calc<cpp_dec_float_50>(opt);
  } else if (opt.prec <= std::numeric_limits<cpp_dec_float_100>::digits10) {
    calc<cpp_dec_float_100>(opt);
  } else {
    std::cerr << "Error: Required precision is too high\n"; return 127;
  }
}

max_stars_repo_name: todo-group/exact

max_issues_repo_name: todo-group/exact

max_forks_repo_name: todo-group/exact


text:
#include "PsfRarArchive.h"
#include <vector>
#include <boost/algorithm/string.hpp>
#include <unrar/rar.hpp>
#include "string_cast.h"
#include "stricmp.h"

static Archive* ConvertArchive(void* archivePtr)
{
	return reinterpret_cast<Archive*>(archivePtr);
}

CPsfRarArchive::CPsfRarArchive()
{
	m_archive = new Archive();
}

CPsfRarArchive::~CPsfRarArchive()
{
	delete ConvertArchive(m_archive);
}

void CPsfRarArchive::Open(const boost::filesystem::path& filePath)
{
	Archive* arc(ConvertArchive(m_archive));
	arc->Open(filePath.wstring().c_str());
	arc->IsArchive(false);
	if(!arc->IsOpened())
	{
		throw std::runtime_error("Couldn't open archive.");
	}

	while(arc->ReadHeader() > 0)
	{
		if(arc->ShortBlock.HeaderType == HEAD_FILE)
		{
			if(!arc->IsArcDir())
			{
				FILEINFO fileInfo;
				fileInfo.name = string_cast<std::string>(arc->FileHead.FileName);
				boost::replace_all(fileInfo.name, "\\", "/");
				fileInfo.length = static_cast<unsigned int>(arc->FileHead.UnpSize);
				m_files.push_back(fileInfo);
			}
		}
		arc->SeekToNext();
	}
}

void CPsfRarArchive::ReadFileContents(const char* fileName, void* buffer, unsigned int bufferLength)
{
	Archive* arc(ConvertArchive(m_archive));
	if(!arc->IsOpened())
	{
		throw std::runtime_error("Archive isn't opened.");
	}

	std::string fixedFileName(fileName);
	boost::replace_all(fixedFileName, "/", "\\");

	arc->Seek(0, SEEK_SET);

	ComprDataIO dataIo;
	dataIo.Init();

	Unpack unpack(&dataIo);

	while(arc->ReadHeader() > 0)
	{
		if(arc->ShortBlock.HeaderType == HEAD_FILE)
		{
			if(!arc->IsArcDir())
			{
				bool isGoodFile = !stricmp(fixedFileName.c_str(), string_cast<std::string>(arc->FileHead.FileName).c_str());

				dataIo.SetFiles(arc, NULL);
				dataIo.SetPackedSizeToRead(arc->FileHead.PackSize);

				dataIo.CurUnpRead = 0;
				dataIo.CurUnpWrite = 0;
				dataIo.UnpHash.Init(arc->FileHead.FileHash.Type, 1);
				dataIo.PackedDataHash.Init(arc->FileHead.FileHash.Type, 1);
				dataIo.SetTestMode(!isGoodFile);

				if(isGoodFile)
				{
					dataIo.SetUnpackToMemory(reinterpret_cast<byte*>(buffer), bufferLength);
				}

				unpack.Init(arc->FileHead.WinSize, arc->FileHead.Solid);
				unpack.SetDestSize(arc->FileHead.UnpSize);

				if(arc->FileHead.Method == 0x30)
				{
					std::vector<byte> unstoreBuffer;
					unstoreBuffer.resize(0x10000);
					uint toReadSize = arc->FileHead.UnpSize;
					while(1)
					{
						uint code = dataIo.UnpRead(&unstoreBuffer[0], unstoreBuffer.size());
						if(code == 0 || code == -1) break;
						code = code < toReadSize ? code : toReadSize;
						dataIo.UnpWrite(&unstoreBuffer[0], code);
						if(toReadSize >= 0)
						{
							toReadSize -= code;
						}
					}
				}
				else
				{
					unpack.DoUnpack(arc->FileHead.UnpVer, arc->FileHead.Solid);
				}

				if(!dataIo.UnpHash.Cmp(&arc->FileHead.FileHash, arc->FileHead.UseHashKey ? arc->FileHead.HashKey : nullptr))
				{
					throw std::runtime_error("CRC check error.");
				}

				if(isGoodFile)
				{
					return;
				}
			}
		}
		arc->SeekToNext();
	}

	throw std::runtime_error("Couldn't read file from archive.");
}

max_stars_repo_name: maximu/Play-

max_issues_repo_name: maximu/Play-

max_forks_repo_name: maximu/Play-


text:
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <signal.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <getopt.h>
#include <nlohmann/json.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <sstream>

using nlohmann::json;

#include <pulsar/Client.h>
#include <lib/LogUtils.h>

DECLARE_LOG_OBJECT()

using namespace pulsar;

std::string    pipe_file_name = "";
bool           enabeDebug = false;
std::string    pulsar_url = "";
std::string    pulsar_topic = "";

std::string& ltrim(std::string &s)
{
    auto it = std::find_if(s.begin(), s.end(),
                           [](char c) {
                               return !std::isspace<char>(c, std::locale::classic());
                           });
    s.erase(s.begin(), it);
    return s;
}

std::string& rtrim(std::string &s)
{
    auto it = std::find_if(s.rbegin(), s.rend(),
                           [](char c) {
                               return !std::isspace<char>(c, std::locale::classic());
                           });
    s.erase(it.base(), s.end());
    return s;
}

bool contains(std::string s, std::string sub){
    return s.find(sub) != std::string::npos;
}

std::string& trim(std::string &s) {
    return ltrim(rtrim(s));
}

bool startsWith(std::string s, std::string sub){
    return s.find(sub)==0? true:false;
}

bool endsWith(std::string s,std::string sub){
    return s.rfind(sub)==(s.length()-sub.length())?true:false;
}

int next(std::string pkt,int state ,std::size_t *lpos, std::size_t *offset) {
    std::string trimed = trim(pkt).substr(*lpos);

    *offset = 0;
    if(startsWith(trimed,"//")){
        *lpos = std::string::npos;
        *offset = std::string::npos;
        return -2; //comments
    }

    //{A{B{C}C}E}
    std::size_t lfound = trimed.find_first_of("{");
    std::size_t rfound = trimed.find_first_of("}");

    //XXX
    if(std::string::npos == rfound && std::string::npos == lfound){
        *offset = trimed.length();
        return -1; //only contents
    }

    //XXX}
    if(std::string::npos == lfound){
        *offset = rfound + 1;
        return 1; //}
    }

    //XXX{
    if(std::string::npos == rfound){
        *offset = lfound + 1;
        return 0; //{
    }

    //XXX{}
    if(lfound<rfound){
        *offset = lfound + 1;
        return 0; //{
    }

    //XXX}XX{
    if(lfound>rfound){
        *offset = rfound + 1;
        return 1; //}
    }

    return state;
}

std::string compress(const std::string &data) {
    boost::iostreams::filtering_streambuf<boost::iostreams::output> output_stream;
    output_stream.push(boost::iostreams::gzip_compressor());
    std::stringstream string_stream;
    output_stream.push(string_stream);
    boost::iostreams::copy(boost::iostreams::basic_array_source<char>(data.c_str(),
                                                                      data.size()), output_stream);
    return string_stream.str();
}

std::string decompress(const std::string &cipher_text) {
    std::stringstream string_stream;
    string_stream << cipher_text;
    boost::iostreams::filtering_streambuf<boost::iostreams::input> input_stream;
    input_stream.push(boost::iostreams::gzip_decompressor());

    input_stream.push(string_stream);
    std::stringstream unpacked_text;
    boost::iostreams::copy(input_stream, unpacked_text);
    return unpacked_text.str();
}

static void
sigHandler(int sig)
{
    static int count = 0;

    if (sig == SIGINT) {
        count++;
        printf("Caught SIGINT (%d)\n", count);

        if(count > 2){
            exit(EXIT_SUCCESS);
        }
        return;
    }

    printf("Caught SIGQUIT - Exited!\n");
    exit(EXIT_SUCCESS);
}

void PrintHelp()
{
    std::cout <<
            "-p, --pipe <name>:       Input pipe name\n"
            "-d, --debug:             Enable debug\n"
            "-t, --topic <non-persistent|persistent://<tenant>/<ns>/<topic>>:             pulsar Topic to send to\n"
            "-m, --pulsar <url>:      Set pulsar MQ address\n"
            "h|?, --help:              Show help\n";
    exit(1);
}

void ProcessArgs(int argc, char** argv)
{
    const char* const short_opts = "p:dt:m:h";
    const option long_opts[] = {
            {"pipe", required_argument, nullptr, 'p'},
            {"debug", no_argument, nullptr, 'd'},
            {"topic", required_argument, nullptr, 't'},
            {"pulsar", required_argument, nullptr, 'm'},
            {"help", no_argument, nullptr, 'h'},
            {nullptr, no_argument, nullptr, 0}
    };

    while (true)
    {
        const auto opt = getopt_long(argc, argv, short_opts, long_opts, nullptr);

        if (-1 == opt)
            break;

        switch (opt)
        {
        case 'p':
            pipe_file_name = std::string(optarg);
            break;
        case 'd':
            enabeDebug = true;
            break;
        case 't':
            pulsar_topic = std::string(optarg);
            break;
        case 'm':
            pulsar_url = std::string(optarg);
            break;
        case 'h': // -h or --help
        case '?': // Unrecognized option
        default:
            PrintHelp();
            break;
        }
    }
}

void callback(Result code, const MessageId& msgId) {
    if(enabeDebug) {
        LOG_INFO("Pular Recved code: " << code << " -- MsgID: " << msgId);
    }
}

int main(int argc, char* args[]) {
    if (signal(SIGINT, sigHandler) == SIG_ERR){
        exit(1);
    }

    if (signal(SIGQUIT, sigHandler) == SIG_ERR){
        exit(1);
    }

    ProcessArgs(argc,args);

    if(pipe_file_name == ""){
       PrintHelp();
    }

    if(pulsar_url == ""){
       PrintHelp();
    }

    if(pulsar_topic == ""){
        pulsar_topic = "non-persistent://public/default/ntrafic";
    }

    Client client(pulsar_url);

    Producer producer;

    //Result result = client.createProducer(pulsar_topic, producer);
    // if (result != ResultOk) {
    //     LOG_ERROR("Error creating producer: " << result);
    //     return -1;
    // }
    client.createProducer(pulsar_topic, producer);

    //initialize pipeline
    std::ifstream pipein(pipe_file_name);
    std::stringstream sstreamin;
    std::vector<std::string> stack;
    std::string packet;
    int state = 0; //{ == 0, } == 1 BLANK -1

    while(true)
    {
        if ( pipein.fail() ){
            pipein.close();
            usleep(100);
            pipein = std::ifstream(pipe_file_name);
        }

        while(std::getline(pipein, packet)){
            packet = trim(packet);
            if(startsWith(packet,"//")){
                continue;
            }

            if(sstreamin.str().size() > 200000){ //reset if size too big,robust way
                sstreamin.clear();
                sstreamin.str("");
                stack.clear();
            }

            if(stack.empty() && !startsWith(packet,"{")){ //started only with a full package
                sstreamin.clear();
                sstreamin.str("");
                continue;
            }

            std::size_t lpos = 0;
            std::size_t offset = 0;

            if(enabeDebug) {
                LOG_INFO("Recved: " << packet);
            }

            while(true) {
               state = next(packet, state, &lpos, &offset);
               if(enabeDebug) {
                    LOG_INFO("||state:" << state << " lpos:" << lpos << " offset:" << offset);
               }

               if (state == 0) {
                    stack.push_back("{");
                    sstreamin << packet.substr(lpos, offset);
                    if(enabeDebug){
                        LOG_INFO("||0:sstreamin:" << sstreamin.str());
                    }
               } else if (state == 1) {
                    stack.pop_back();
                    sstreamin << packet.substr(lpos, offset);
                    if(enabeDebug){
                        LOG_INFO("||1:sstreamin:" << sstreamin.str());
                    }
               } else if (state == -1) {
                    sstreamin << packet.substr(lpos, offset);
                    if(enabeDebug){
                        LOG_INFO("||2:sstreamin:" << sstreamin.str());
                    }
               }

               if(enabeDebug) {
                    LOG_INFO("Status: " << stack.size() << " | " << sstreamin.str().size());
               }

               if(stack.empty()) {
                    if(enabeDebug){
                        LOG_INFO("||3:sstreamin:" << sstreamin.str());
                    }

                    std::string json_packet = sstreamin.str();
                    if(endsWith(json_packet,"},\n")) {
                        json_packet = json_packet.substr(0, json_packet.size()-2);
                    }
                    if(endsWith(json_packet,"},")) {
                        json_packet = json_packet.substr(0, json_packet.size()-1);
                    }

                    if(json_packet.length() > 0) {
                        Message msg = MessageBuilder().setContent(compress(json_packet)).build();
                        producer.sendAsync(msg, callback);

                        if(enabeDebug){
                            if(json_packet.length() > 100){
                                LOG_INFO("Message async sending queued: " << "||" << json_packet.substr(0,100) << "\n ..... \n"<<json_packet.substr(json_packet.length()-100,json_packet.length()));
                            } else {
                                LOG_INFO("Message async sending queued: " << "||" << json_packet);
                            }
                        }
                    }

                    if(enabeDebug){
                        LOG_INFO("||4:sstreamin:" << sstreamin.str());
                    }

                    sstreamin.clear();
                    sstreamin.str("");
                }else{
                    // if(enabeDebug){
                    //     LOG_INFO("||4:sstreamin:" << sstreamin.str());
                    // }
                }

               lpos = lpos + offset;
               if(lpos >= packet.length()) {
                    break;
               }
            }
            sstreamin << std::endl;
        }
    }

    client.close();
    pipein.close();
}

ext: cc

max_stars_repo_name: quick-meduo/pulsar

max_issues_repo_name: quick-meduo/pulsar

max_forks_repo_name: quick-meduo/pulsar


text:
#include <cstddef>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <limits>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <boost/program_options.hpp>
#include <univalue.h>
#include <insertionfinder/fallbacks/filesystem.hpp>
#include <insertionfinder/algorithm.hpp>
#include <insertionfinder/case.hpp>
#include <insertionfinder/cube.hpp>
#include <insertionfinder/termcolor.hpp>
#include <insertionfinder/improver/improver.hpp>
#include <insertionfinder/improver/slice.hpp>
#include "../utils/encoding.hpp"
#include "commands.hpp"
#include "utils.hpp"
using std::size_t;
namespace fs = std::filesystem;
namespace po = boost::program_options;
using InsertionFinder::Algorithm;
using InsertionFinder::Case;
using InsertionFinder::Cube;
using InsertionFinder::Improver;
using InsertionFinder::Insertion;
using InsertionFinder::SliceImprover;
using InsertionFinder::Solution;
namespace CLI = InsertionFinder::CLI;
namespace Details = InsertionFinder::Details;

namespace {
    struct Printer {
        virtual void print_case_information(const Algorithm& skeleton) {}
        virtual void print_result(
            const Algorithm& skeleton,
            const Improver& improver, Improver::Result result,
            bool expand
        ) = 0;
        virtual ~Printer() = default;
    };

    struct StandardPrinter: Printer {
        void print_case_information(const Algorithm& skeleton) override {
            std::cout << termcolor::bold << "Skeleton: " << termcolor::reset << skeleton;
            if (skeleton.length()) {
                std::cout << " (" << termcolor::yellow << skeleton.length() << termcolor::reset << "f)";
            }
            std::cout << std::endl;
        }

        void print_result(
            const Algorithm& skeleton,
            const Improver& improver, Improver::Result result,
            bool expand
        ) override {
            if (improver.get_fewest_moves() == skeleton.length()) {
                std::cout << "No improvements found." << std::endl;
            } else {
                const auto& solutions = improver.get_solutions();
                for (size_t index = 0; index < solutions.size(); ++index) {
                    const Solution& solution = solutions[index];
                    std::cout << std::endl
                        << termcolor::bold << "Improvement #" << index + 1 << termcolor::reset << std::endl;
                    if (expand) {
                        std::cout << solution;
                    } else {
                        solution.print(std::cout, solution.merge_insertions(skeleton));
                    }
                    std::cout << std::endl;
                }
            }
            Details::print_duration(std::cout, result.duration);
        }
    };

    struct JSONPrinter: Printer {
        void print_result(
            const Algorithm& skeleton,
            const Improver& improver, Improver::Result result,
            bool expand
        ) override {
            UniValue map(UniValue::VOBJ);
            map.pushKV("skeleton", skeleton.str());
            const auto& solutions = improver.get_solutions();
            map.pushKV("fewest_moves", static_cast<int>(improver.get_fewest_moves()));
            UniValue solution_list(UniValue::VARR);
            for (const Solution& solution: solutions) {
                solution_list.push_back(Details::create_json_solution(skeleton, solution));
            }
            map.pushKV("solutions", solution_list);
            map.pushKV("duration", result.duration);
            std::cout << map.write() << std::flush;
        }
    };
};

void CLI::find_improvements(const po::variables_map& vm) {
    const std::vector<std::string> filenames =
        vm.count("file") ? vm["file"].as<std::vector<std::string>>() : std::vector<std::string>();
    const fs::path algorithms_directory = vm["algs-dir"].as<std::string>();
    std::vector<std::string> algfilenames =
        vm.count("algfile") ? vm["algfile"].as<std::vector<std::string>>() : std::vector<std::string>();

    std::unordered_map<Cube, Case> map;
    for (const std::string& name: algfilenames) {
        std::ifstream fin(name, std::ios::in | std::ios::binary);
        if (fin.fail()) {
            fin = std::ifstream((algorithms_directory / (name + ".algs")).string(), std::ios::in | std::ios::binary);
            if (fin.fail()) {
                std::cerr << "Failed to open algorithm file " << name << std::endl;
                continue;
            }
        }
        size_t size;
        if (auto x = Details::read_varuint(fin)) {
            size = *x;
        } else {
            std::cerr << "Invalid algorithm file " << name << std::endl;
            continue;
        }
        for (size_t i = 0; i < size; ++i) {
            Case _case;
            try {
                _case.read_from(fin);
            } catch (...) {
                std::cerr << "Invalid algorithm file " << name << std::endl;
                break;
            }
            auto [node, inserted] = map.try_emplace(_case.get_state(), std::move(_case));
            if (!inserted) {
                node->second.merge_algorithms(std::move(_case));
            }
        }
    }

    std::vector<Case> cases;
    cases.reserve(map.size());
    for (auto& node: map) {
        cases.emplace_back(std::move(node.second));
    }
    std::sort(cases.begin(), cases.end(), [](const Case& x, const Case& y) {return Case::compare(x, y) < 0;});

    std::shared_ptr<std::istream> in;
    if (filenames.empty()) {
        in.reset(&std::cin, [](std::istream*) {});
    } else {
        const std::string& name = filenames.front();
        in = std::make_shared<std::ifstream>(name);
        if (in->fail()) {
            throw CLI::CommandExecutionError("Failed to open input file " + name);
        }
    }

    std::string line;
    std::getline(*in, line);
    Algorithm skeleton;
    try {
        skeleton = Algorithm(line);
    } catch (const AlgorithmError& e) {
        throw CLI::CommandExecutionError("Invalid skeleton " + line);
    }
    in.reset();
    skeleton.simplify();

    std::unique_ptr<Printer> printer;
    if (vm.count("json")) {
        printer = std::make_unique<JSONPrinter>();
    } else {
        printer = std::make_unique<StandardPrinter>();
    }
    printer->print_case_information(skeleton);

    std::unique_ptr<Improver> improver = std::make_unique<SliceImprover>(
        skeleton, cases,
        SliceImprover::Options {vm["replacement-threshold"].as<size_t>()}
    );
    size_t max_threads = vm["jobs"].as<size_t>();
    improver->search({max_threads});
    printer->print_result(skeleton, *improver, improver->get_result(), vm.count("expand-insertions"));
}

max_stars_repo_name: cmsxbc/insertionfinder

max_issues_repo_name: cmsxbc/insertionfinder

max_forks_repo_name: cmsxbc/insertionfinder


text:
/*=============================================================================
    Copyright (c) 2001-2007 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#if !defined(BOOST_SPIRIT_NUMERIC_FEB_05_2007_1231PM)
#define BOOST_SPIRIT_NUMERIC_FEB_05_2007_1231PM

#include <boost/spirit/home/qi/numeric/int.hpp>
#include <boost/spirit/home/qi/numeric/uint.hpp>
#include <boost/spirit/home/qi/numeric/real.hpp>
#include <boost/spirit/home/qi/numeric/meta_grammar.hpp>

#endif

ext: hpp

max_stars_repo_name: jaredhoberock/gotham

max_issues_repo_name: jaredhoberock/gotham

max_forks_repo_name: jaredhoberock/gotham


text:
/*
 * Copyright (C) 2012-2014 Open Source Robotics Foundation
 *
 * 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 <gtest/gtest.h>
#include <boost/filesystem.hpp>
#include <stdlib.h>

#include "gazebo/common/Time.hh"
#include "gazebo/common/Console.hh"
#include "test/util.hh"

const int g_messageRepeat = 4;

class Console_TEST : public gazebo::testing::AutoLogFixture { };

/////////////////////////////////////////////////
/// \brief Test Console::Init and Console::Log
TEST_F(Console_TEST, InitAndLog)
{
  // Log the string
  std::string logString = "this is a test";

  gzlog << logString << std::endl;
  EXPECT_TRUE(this->GetLogContent().find(logString) != std::string::npos);
}

//////////////////////////////////////////////////
/// \brief Test Console::Log with \n characters
TEST_F(Console_TEST, LogSlashN)
{
  std::string logString = "this is a log test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzlog << logString << " _n__ " << i << '\n';
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " _n__ " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::Log with std::endl
TEST_F(Console_TEST, LogStdEndl)
{
  std::string logString = "this is a log test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzlog << logString << " endl " << i << std::endl;
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " endl " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorWarn with \n characters
TEST_F(Console_TEST, ColorWarnSlashN)
{
  std::string logString = "this is a warning test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzwarn << logString << " _n__ " << i << '\n';
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " _n__ " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorWarn with std::endl
TEST_F(Console_TEST, ColorWarnStdEndl)
{
  std::string logString = "this is a warning test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzwarn << logString << " endl " << i << std::endl;
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " endl " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorDbg with \n characters
TEST_F(Console_TEST, ColorDbgSlashN)
{
  std::string logString = "this is a dbg test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzdbg << logString << " _n__ " << i << '\n';
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " _n__ " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorDbg with std::endl
TEST_F(Console_TEST, ColorDbgStdEndl)
{
  std::string logString = "this is a dbg test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzdbg << logString << " endl " << i << std::endl;
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " endl " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorMsg with \n characters
TEST_F(Console_TEST, ColorMsgSlashN)
{
  std::string logString = "this is a msg test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzmsg << logString << " _n__ " << i << '\n';
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " _n__ " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorMsg with std::endl
TEST_F(Console_TEST, ColorMsgStdEndl)
{
  std::string logString = "this is a msg test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzmsg << logString << " endl " << i << std::endl;
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " endl " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorErr with \n characters
TEST_F(Console_TEST, ColorErrSlashN)
{
  std::string logString = "this is an error test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzerr << logString << " _n__ " << i << '\n';
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " _n__ " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

//////////////////////////////////////////////////
/// \brief Test Console::ColorErr with std::endl
TEST_F(Console_TEST, ColorErrStdEndl)
{
  std::string logString = "this is an error test";

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    gzerr << logString << " endl " << i << std::endl;
  }

  std::string logContent = this->GetLogContent();

  for (int i = 0; i < g_messageRepeat; ++i)
  {
    std::ostringstream stream;
    stream << logString << " endl " << i;
    EXPECT_TRUE(logContent.find(stream.str()) != std::string::npos);
  }
}

/////////////////////////////////////////////////
/// \brief Test Console::ColorMsg
TEST_F(Console_TEST, ColorMsg)
{
  std::string logString = "this is a msg test";

  gzmsg << logString << std::endl;

  std::string logContent = this->GetLogContent();

  EXPECT_TRUE(logContent.find(logString) != std::string::npos);
}

/////////////////////////////////////////////////
/// \brief Test Console::ColorErr
TEST_F(Console_TEST, ColorErr)
{
  std::string logString = "this is an error test";

  gzerr << logString << std::endl;

  std::string logContent = this->GetLogContent();

  EXPECT_TRUE(logContent.find(logString) != std::string::npos);
}

/////////////////////////////////////////////////
int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

max_stars_repo_name: hyunoklee/Gazebo

max_issues_repo_name: hyunoklee/Gazebo

max_forks_repo_name: hyunoklee/Gazebo


text:
#include <boost/asio.hpp>
#include <iostream>
#include "basic_timer.hpp"
#include "timer_impl.hpp"
#include "basic_timer_service.hpp"

void wait_handler(const boost::system::error_code &ec)
{
  std::cout << "5 s." << std::endl;
}

typedef basic_timer<basic_timer_service<> > timer;

int main()
{
  boost::asio::io_service io_service;
  timer t(io_service);
  t.async_wait(5, wait_handler);
  io_service.run();
}

max_stars_repo_path: Boost/The Boost C++ Libraries/src/7.5.1/main.cpp


text:
#ifndef PRE_JSON_DETAIL_DEJSONIZER_HPP
#define PRE_JSON_DETAIL_DEJSONIZER_HPP

#include <variant>
#include <optional>

#include <boost/mpl/for_each.hpp>
#include <boost/fusion/include/for_each.hpp>

#include <pre/fusion/for_each_member.hpp>

#include <nlohmann/json.hpp>

#include <pre/json/detail/sfinae_enabler.hpp>
#include <pre/json/detail/get_type_name_as_string.hpp>
#include <pre/enums/to_underlying.hpp>

#include <pre/variant/for_each_type.hpp>

namespace pre { namespace json { namespace detail {

  struct dejsonizer {

    dejsonizer(const nlohmann::json& json_object) :
      _json_object(json_object) {}

    template<class T>
    void operator()(const char* name, T& value) const {

      if (_json_object.find(name) != std::end(_json_object)) {
        dejsonizer dejsonizer(_json_object.at(name));
        dejsonizer(value);
      } else {
        throw std::runtime_error(
          "Missing key " + std::string(name) + " in JSON Object : " + _json_object.dump());
      }
    }

    template<class T>
    void operator()(const char* name, std::optional<T>& value) const {
      // std::optional doesn't need to be in the json object
      if (_json_object.find(name) != std::end(_json_object)) {
        dejsonizer dejsonizer(_json_object.at(name));
        dejsonizer(value);
      }
    }

    template<class T>
    void operator()(std::optional<T>& value) const {
      // std::optional doesn't need to be in the json object
      if (!_json_object.empty()) {
        dejsonizer dejsonizer(_json_object);

        T optional_value;
        dejsonizer(optional_value);
        value = optional_value;
      }
    }

    template<class T,
      enable_if_is_adapted_struct_t<T>* = nullptr>
    void operator()(T& value) const {
      if (_json_object.is_object()) {
        pre::fusion::for_each_member(value, *this);
      } else {
        throw std::runtime_error("The JSON Object " + _json_object.dump() + " isn't an object that we can map to an internal type");
      }
    }

    template<typename TVariant>
    struct variant_checker {

      variant_checker(const nlohmann::json& json_object, TVariant& value) : _json_object(json_object), value(value) {
      };

      template< typename U > void operator()(U&& x) {
        if (!successed) {
            auto struct_it = _json_object.find("struct");

            if ( (struct_it != _json_object.end()) &&
                (*struct_it == get_type_name_as_string<U>()) ) {

              dejsonizer dejsonizer(_json_object);
              U test_value;
              dejsonizer(test_value);
              successed = true;
              value = test_value;
            }
        }
      }

      private:
        const nlohmann::json& _json_object;
        TVariant &value;
        bool successed = false;
    };

    template<class T,
      enable_if_is_variant_t<T>* = nullptr>
    void operator()(T& value) const {
      pre::variant::for_each_type( value, variant_checker<T>(_json_object, value) );
    }

    template<class T,
      typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
    void operator()(T& value) const {
      // XXX : How could we safe range check enum assignement ?
      value = static_cast<T>(_json_object.get<typename std::underlying_type<T>::type>());
    }

    template<class T,
      enable_if_is_chrono_duration_t<T>* = nullptr>
    void operator()(T& value) const {
      value = T{_json_object.get<typename T::rep>()};
    }

    template<class T,
      enable_if_is_directly_serializable_t<T>* = nullptr>
    void operator()(T& value) const {
      //TODO: Better diagnostic, current exception is : std::exception::what: type must be number, but is string, we should reoutput the json object in this case.
      value = _json_object.get<T>();
    }

    template<class T,
      enable_if_is_container_t<T>* = nullptr>
    void operator()(T& value) const {
      if (_json_object.is_array()) {

        value.clear(); //XXX: Needed to clear if already somehow full ?
        // XXX: Not supported by all containers : value.reserve(array.size());
        for (auto entry_json : _json_object) {
          typename T::value_type entry_deser;
          dejsonizer dejsonizer(entry_json);
          dejsonizer(entry_deser);
          value.push_back(entry_deser);
        }

      } else {
        throw std::runtime_error("Expected " + _json_object.dump() + " to be a json array.");
      }

    }

    template<class T,
      enable_if_is_associative_container_t<T>* = nullptr>
    void operator()(T& value) const {
      if (_json_object.is_object()) {

        value.clear();

        for (nlohmann::json::const_iterator it = _json_object.begin(); it != _json_object.end(); ++it) {
          typename T::mapped_type entry_deser;
          dejsonizer dejsonizer(it.value());
          dejsonizer(entry_deser);
          value[it.key()] = entry_deser;
        }

      } else {
        throw std::runtime_error("Expected " + _json_object.dump() + " to be a json object.");
      }
    }

    private:
      const nlohmann::json& _json_object; // XXX: Invert to be the same as jsonizer

  };

}}}

#endif

max_stars_repo_name: cpp-pre/json

max_issues_repo_name: cpp-pre/json

max_forks_repo_name: cpp-pre/json


text:
#include <boost/test/unit_test.hpp>

#include <util/driver/value/Value.h>

using namespace izenelib::driver;

namespace { // {anonymous}
struct ValueFixture
{
    Value arrayValue;
    Value objectValue;

    ValueFixture()
    {
        Value::ArrayType array;
        array.push_back(1);
        arrayValue = array;

        Value::ObjectType object;
        object["test"] = 1;
        objectValue = object;
    }
};

} // namespace {anonymous}

BOOST_FIXTURE_TEST_SUITE(Clear_test, ValueFixture)

BOOST_AUTO_TEST_CASE(NullValue_test)
{
    Value v;
    v.clear();
    BOOST_CHECK(v == nullValue);
}

BOOST_AUTO_TEST_CASE(Int_test)
{
    Value v(1);
    v.clear();
    BOOST_CHECK(0 == v);
}

BOOST_AUTO_TEST_CASE(Uint_test)
{
    Value v(1U);
    v.clear();
    BOOST_CHECK(0U == v);
}

BOOST_AUTO_TEST_CASE(Bool_test)
{
    Value v(true);
    v.clear();
    BOOST_CHECK(false == v);
}

BOOST_AUTO_TEST_CASE(Str_test)
{
    Value v("abcdef");
    v.clear();
    BOOST_CHECK("" == v);
}

BOOST_AUTO_TEST_CASE(Array_test)
{
    arrayValue.clear();
    BOOST_CHECK(arrayValue.size() == 0);
    BOOST_CHECK(arrayValue.type() == Value::kArrayType);
}

BOOST_AUTO_TEST_CASE(Object_test)
{
    objectValue.clear();
    BOOST_CHECK(objectValue.size() == 0);
    BOOST_CHECK(objectValue.type() == Value::kObjectType);
}

BOOST_AUTO_TEST_SUITE_END() // Set_test

max_stars_repo_name: izenecloud/izenelib

max_issues_repo_name: izenecloud/izenelib

max_forks_repo_name: izenecloud/izenelib