<commit_before>/*
 * libaps.cpp - Library for APSv2 control. 
 *
 */

#include <sstream>
#include "headings.h"
#include "libaps2.h"
#include "APS2.h"
#include "APSEthernet.h"
#include "asio.hpp"

weak_ptr<APSEthernet> ethernetRM; //resource manager for the asio ethernet interface
map<string, APS2> APSs; //map to hold on to the APS instances
set<string> deviceSerials; // set of APSs that responded to an enumerate broadcast

// stub class to close the logger file handle when the driver goes out of scope
class InitAndCleanUp {
public:
	InitAndCleanUp();
	~InitAndCleanUp();
};

InitAndCleanUp::InitAndCleanUp() {
	//Open the default log file
	FILE* pFile = fopen("libaps2.log", "a");
	Output2FILE::Stream() = pFile;
}

InitAndCleanUp::~InitAndCleanUp() {
	if (Output2FILE::Stream()) {
		fclose(Output2FILE::Stream());
	}
}
InitAndCleanUp initandcleanup_;

shared_ptr<APSEthernet> get_interface() {
	//See if we have to setup our own RM
	shared_ptr<APSEthernet> myEthernetRM = ethernetRM.lock();

	if (!myEthernetRM) {
		myEthernetRM = std::make_shared<APSEthernet>();
		ethernetRM = myEthernetRM;
	}

	return myEthernetRM;
}

//Handle exceptions thrown in library calls
APS2_STATUS make_errno(std::exception_ptr e){
	FILE_LOG(logERROR) << "Oops!";
	return APS2_UNKNOWN_ERROR;
}

//It seems Args1 and Args2 should match but I couldn't get the parameter pack tempalte deduction to work
template<typename R, typename... Args1, typename... Args2>
APS2_STATUS aps_call(const char * deviceSerial, std::function<R(Args1...)> func, Args2&&... args){
	try{
		func(APSs[deviceSerial], std::forward<Args2>(args)...);
		//Nothing thrown then assume OK
		return APS2_OK;
	}
	catch(...) {
		return make_errno(std::current_exception());
	}
}

#ifdef __cplusplus
extern "C" {
#endif

APS2_STATUS get_numDevices(unsigned int * numDevices) {
	/*
	Returns the number of APS2s that respond to a broadcast status request.
	*/
	deviceSerials = get_interface()->enumerate();
	*numDevices = deviceSerials.size();
	return APS2_OK;
}

APS2_STATUS get_deviceSerials(const char ** deviceSerialsOut) {
	/*
	Fill in an array of char* with null-terminated char arrays with the
	enumerated device ip addresses.
	Assumes sufficient memory has been allocated
	*/
	size_t ct = 0;
	for (auto & serial : deviceSerials) {
		deviceSerialsOut[ct] = serial.c_str();
		ct++;
	}
	return APS2_OK;
}

APS2_STATUS connect_APS(const char * deviceSerial) {
	/*
	Connect to a device specified by serial number string
	Assumes null-terminated deviceSerial
	*/
	string serial = string(deviceSerial);
	// create the APS2 object if it is not already in the map
	if (APSs.find(serial) == APSs.end()) {
		APSs[serial] = APS2(serial);
	}
	return APSs[serial].connect(get_interface());
}

//Assumes a null-terminated deviceSerial
APS2_STATUS disconnect_APS(const char * deviceSerial) {
	APS2_STATUS result = APSs[string(deviceSerial)].disconnect();
	APSs.erase(string(deviceSerial));
	return result;
}

int reset(const char * deviceSerial, int resetMode) {
	return APSs[string(deviceSerial)].reset(static_cast<APS_RESET_MODE_STAT>(resetMode));
}

//Initialize an APS unit
//Assumes null-terminated bitFile
int initAPS(const char * deviceSerial, int forceReload) {
	aps_call(deviceSerial, std::function<APS2_STATUS(APS2&, const bool&, const int&)>(&APS2::init), bool(forceReload), 0);
	return 0;
	// return APSs[string(deviceSerial)].init(forceReload);
}

int get_firmware_version(const char * deviceSerial) {
	return APSs[string(deviceSerial)].get_firmware_version();
}

double get_uptime(const char * deviceSerial) {
	return APSs[string(deviceSerial)].get_uptime();
}

int set_sampleRate(const char * deviceSerial, int freq) {
	return APSs[string(deviceSerial)].set_sampleRate(freq);
}

int get_sampleRate(const char * deviceSerial) {<commit_msg>Try a aps_getter templated functor as well.<commit_after>/*
 * libaps.cpp - Library for APSv2 control. 
 *
 */

#include <sstream>
#include "headings.h"
#include "libaps2.h"
#include "APS2.h"
#include "APSEthernet.h"
#include "asio.hpp"

weak_ptr<APSEthernet> ethernetRM; //resource manager for the asio ethernet interface
map<string, APS2> APSs; //map to hold on to the APS instances
set<string> deviceSerials; // set of APSs that responded to an enumerate broadcast

// stub class to close the logger file handle when the driver goes out of scope
class InitAndCleanUp {
public:
	InitAndCleanUp();
	~InitAndCleanUp();
};

InitAndCleanUp::InitAndCleanUp() {
	//Open the default log file
	FILE* pFile = fopen("libaps2.log", "a");
	Output2FILE::Stream() = pFile;
}

InitAndCleanUp::~InitAndCleanUp() {
	if (Output2FILE::Stream()) {
		fclose(Output2FILE::Stream());
	}
}
InitAndCleanUp initandcleanup_;

shared_ptr<APSEthernet> get_interface() {
	//See if we have to setup our own RM
	shared_ptr<APSEthernet> myEthernetRM = ethernetRM.lock();

	if (!myEthernetRM) {
		myEthernetRM = std::make_shared<APSEthernet>();
		ethernetRM = myEthernetRM;
	}

	return myEthernetRM;
}

//Handle exceptions thrown in library calls
APS2_STATUS make_errno(std::exception_ptr e){
	FILE_LOG(logERROR) << "Oops!";
	return APS2_UNKNOWN_ERROR;
}

//It seems Args1 and Args2 should match but I couldn't get the parameter pack template deduction to work
template<typename R, typename... Args1, typename... Args2>
APS2_STATUS aps2_call(const char * deviceSerial, std::function<R(Args1...)> func, Args2&&... args){
	try{
		func(APSs[deviceSerial], std::forward<Args2>(args)...);
		//Nothing thrown then assume OK
		return APS2_OK;
	}
	catch(...) {
		return make_errno(std::current_exception());
	}
}

template<typename R, typename... Args1, typename... Args2>
APS2_STATUS aps2_getter(const char * deviceSerial, std::function<R(Args1...)> func, R *resPtr,  Args2&&... args){
	try{
		*resPtr = func(APSs[deviceSerial], std::forward<Args2>(args)...);
		//Nothing thrown then assume OK
		return APS2_OK;
	}
	catch(...) {
		return make_errno(std::current_exception());
	}
}

#ifdef __cplusplus
extern "C" {
#endif

APS2_STATUS get_numDevices(unsigned int * numDevices) {
	/*
	Returns the number of APS2s that respond to a broadcast status request.
	*/
	deviceSerials = get_interface()->enumerate();
	*numDevices = deviceSerials.size();
	return APS2_OK;
}

APS2_STATUS get_deviceSerials(const char ** deviceSerialsOut) {
	/*
	Fill in an array of char* with null-terminated char arrays with the
	enumerated device ip addresses.
	Assumes sufficient memory has been allocated
	*/
	size_t ct = 0;
	for (auto & serial : deviceSerials) {
		deviceSerialsOut[ct] = serial.c_str();
		ct++;
	}
	return APS2_OK;
}

APS2_STATUS connect_APS(const char * deviceSerial) {
	/*
	Connect to a device specified by serial number string
	Assumes null-terminated deviceSerial
	*/
	string serial = string(deviceSerial);
	// create the APS2 object if it is not already in the map
	if (APSs.find(serial) == APSs.end()) {
		APSs[serial] = APS2(serial);
	}
	return APSs[serial].connect(get_interface());
}

//Assumes a null-terminated deviceSerial
APS2_STATUS disconnect_APS(const char * deviceSerial) {
	APS2_STATUS result = APSs[string(deviceSerial)].disconnect();
	APSs.erase(string(deviceSerial));
	return result;
}

int reset(const char * deviceSerial, int resetMode) {
	return APSs[string(deviceSerial)].reset(static_cast<APS_RESET_MODE_STAT>(resetMode));
}

//Initialize an APS unit
//Assumes null-terminated bitFile
int initAPS(const char * deviceSerial, int forceReload) {
	aps2_call(deviceSerial, std::function<APS2_STATUS(APS2&, const bool&, const int&)>(&APS2::init), bool(forceReload), 0);
	return 0;
	// return APSs[string(deviceSerial)].init(forceReload);
}

int get_firmware_version(const char * deviceSerial) {
	int silly;
	APS2_STATUS status = aps2_getter(deviceSerial, std::function<int(APS2&)>(&APS2::get_firmware_version), &silly);
	cout << silly; 
	return 0;
}

double get_uptime(const char * deviceSerial) {
	return APSs[string(deviceSerial)].get_uptime();
}

int set_sampleRate(const char * deviceSerial, int freq) {
	return APSs[string(deviceSerial)].set_sampleRate(freq);
}

int get_sampleRate(const char * deviceSerial) {
{'fraction_non_alphanumeric': 0.1254795198614033, 'fraction_numerical': 0.010518500185620592, 'mean_word_length': 5.236111111111111, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '766866', 'n_tokens_mistral': 2891, 'n_tokens_neox': 2785, 'n_words': 727}