Skip to content
Snippets Groups Projects
Packet_Structure_Json.cpp 3.94 KiB
Newer Older
Valerio Pastore's avatar
Valerio Pastore committed
/*
**************************************************************************
* Copyright (C) 2023 INAF
* 
* This program is free software: you can redistribute it and/or modify it 
* under the terms of the GNU Lesser General Public License as published by 
* the Free Software Foundation, either version 3 of the License
* or (at your option) any later version. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even 
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
* See the GNU Lesser General Public License for more details. 
* You should have received a copy of the GNU Lesser General Public License 
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* 
* Authors:
* 
* <>Valerio Pastore INAF-OAS Bologna  valerio.pastore@inaf.it
****************************************************************************
*/
astri's avatar
astri committed
#include <Packet_Structure_Json.h>
Valerio Pastore's avatar
Valerio Pastore committed
#include <ctime>
Valerio Pastore's avatar
Valerio Pastore committed

using namespace inaf::oasbo::Packets;
using Structure = std::vector<std::tuple<uint, std::string, uint>>;
Structure PacketStructureJson::readStructureFromSource(std::string source) {
	Structure s_empty;
Valerio Pastore's avatar
Valerio Pastore committed
	std::ifstream file;
	file.open(source, std::ios::in);
Valerio Pastore's avatar
Valerio Pastore committed
	if (!file.is_open()) { // error handling
Valerio Pastore's avatar
.  
Valerio Pastore committed
		time_t now = time(nullptr);
		std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
				<< "]\t[PacketStructure Json]\t" << "Could not open file: "
				<< source << std::endl;
		std::cerr << "\t Returning empty structure" << std::endl;
		return s_empty;
Valerio Pastore's avatar
Valerio Pastore committed
	}
Valerio Pastore's avatar
Valerio Pastore committed
	uint count = 0;
	ordered_json data;
	try {
		file >> data;
	} catch (nlohmann::detail::parse_error &ex) {
Valerio Pastore's avatar
.  
Valerio Pastore committed
		time_t now = time(nullptr);
		std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
				<< "]\t[PacketStructure Json]\t" << ex.what()
				<< "\n\t\tReturning empty structure" << std::endl;
		return s_empty;
	}
	std::optional<Structure> s_tmp = convertToTupleVector(data, count);
Valerio Pastore's avatar
Valerio Pastore committed
	file.close();
	if (s_tmp.has_value())
		return s_tmp.value();
Valerio Pastore's avatar
.  
Valerio Pastore committed
	time_t now = time(nullptr);
	std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
			<< "]\t[PacketStructure Json]\t" << "Returning empty structure"
			<< std::endl;
	return s_empty;
std::optional<Structure> PacketStructureJson::convertToTupleVector(
		const ordered_json &data, uint &count) {
	std::optional<Structure> out = Structure();
astri's avatar
astri committed
	for (auto it = data.begin(); it != data.end(); ++it) {
Valerio Pastore's avatar
Valerio Pastore committed
		if (it.value().is_object()) { // array found
			if (it.value().find("size") == it.value().end() // error handling
Valerio Pastore's avatar
.  
Valerio Pastore committed
			|| it.value().find("fields") == it.value().end()
astri's avatar
astri committed
					|| it.value().size() != 2) {
Valerio Pastore's avatar
.  
Valerio Pastore committed
				time_t now = time(nullptr);
				std::cerr << "["
						<< std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
						<< "]\t[PacketStructure Json]\t" << "Error in file: "
						<< it.value().dump() << std::endl;
				return std::nullopt;
Valerio Pastore's avatar
Valerio Pastore committed
			}
Valerio Pastore's avatar
Valerio Pastore committed
			for (uint i = 0; i < it.value()["size"]; i++) { // convert to tuple vector the json array
				std::optional<Structure> subArray = convertToTupleVector(
						it.value()["fields"], count).value();
				if (!subArray.has_value())
					return std::nullopt;
				std::for_each(subArray.value().begin(), subArray.value().end(),
Valerio Pastore's avatar
Valerio Pastore committed
						[i](std::tuple<uint, std::string, uint> &line) {
							std::get<1>(line).append("_#").append(
									std::to_string(i));
Valerio Pastore's avatar
Valerio Pastore committed
						});
				out.value().insert(out.value().end(), subArray.value().begin(),
						subArray.value().end());
Valerio Pastore's avatar
Valerio Pastore committed
			}
Valerio Pastore's avatar
Valerio Pastore committed
		} else { // single field found
			if (!it.value().is_number_integer()) { // error handling
Valerio Pastore's avatar
.  
Valerio Pastore committed
				time_t now = time(nullptr);
				std::cerr << "["
						<< std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
						<< "]\t[PacketStructure Json]\t" << "Not an int: "
						<< it.value().dump() << std::endl;
				return std::nullopt;
Valerio Pastore's avatar
Valerio Pastore committed
			}
astri's avatar
astri committed
			std::string fieldName(it.key());
Valerio Pastore's avatar
Valerio Pastore committed
			std::transform(fieldName.begin(), fieldName.end(),
					fieldName.begin(), ::tolower);
			out.value().push_back(
Valerio Pastore's avatar
.  
Valerio Pastore committed
					std::make_tuple(count, fieldName, it.value()));
Valerio Pastore's avatar
Valerio Pastore committed
			count += 1;
		}
	}
	return out;
}