text:
#include <lsl_cpp.h>
#include <boost/date_time.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <vector>
#include "wiiuse.h"

using namespace std;
using namespace lsl;

const int max_wiimotes = 4;
const bool enable_sensors = true;

const char* const expansion_names[] = {"None","Nunchuk","Classic","GuitarHero3","WiiBoard","Unknown","Unknown","Unknown"};

/*
TODO:
- reduce orient and accel thresholds to scientific precision
*/

int main(int argc, char* argv[]) {
	wiimote** wiimotes;
	int num_found=0, num_connected=0;
	try {
		// initialize an array of wiimote objects.
		wiimotes = wiiuse_init(max_wiimotes);
		wiiuse_set_bluetooth_stack(wiimotes, max_wiimotes,WIIUSE_STACK_MS);

		// retrieve wiimotes that are in discovery mode
		while (!(num_found = wiiuse_find(wiimotes, max_wiimotes,5))) {
			cout << endl << "No Wiimotes have been found." << endl << endl <<
				"To connect your Wiimote, right-click the bluetooth" << endl <<
				"icon in your Windows taskbar and click 'Add a Device'." << endl <<
				"Now press buttons 1 & 2 on your Wiimote to make it" << endl <<
				"discoverable for 20 seconds. It should show up in your" << endl <<
				"device list as Nintendo RVL-CNT-01 or similar." << endl <<
				"Add this device and select 'pair this device without" << endl <<
				"using a code'." << endl <<
				"Press [Enter] when you are ready or Ctrl-C " << endl <<
				"to terminate the program." << endl;
			cin.get();
		}
		cout << "Found " << num_found << " wiimotes." << endl;

		// connect one or more of the wiimotes
		if (!(num_connected = wiiuse_connect(wiimotes, max_wiimotes)))
			throw runtime_error("Failed to connect to any Wiimote.");

		// indicate that we got connected successfully by a brief rumble
		for (int k=0;k<num_connected;k++)
			wiiuse_rumble(wiimotes[k],1);
		boost::this_thread::sleep(boost::posix_time::millisec(500));
		for (int k=0;k<num_connected;k++)
			wiiuse_rumble(wiimotes[k],0);

		if (num_connected < num_found)
			cout << "Warning: could not connect to all Wiimotes that were found." << endl;
		else
			cout << "Successfully connected to all Wiimotes." << endl;

		// check battery status and warn if necessary
		for (int k=0;k<num_connected;k++) {
			wiiuse_status(wiimotes[k]);
			if (wiimotes[k]->battery_level && (wiimotes[k]->battery_level < 0.2))
				cout << "Warning: The battery level of Wii #" << k+1 << " is at " << (int)(100*wiimotes[k]->battery_level) << " percent." << endl;
		}

		// open an outlet for each wiimote's event stream
		vector<boost::shared_ptr<stream_outlet> > marker_outlets;
		vector<boost::shared_ptr<stream_outlet> > sensor_outlets;
		for (int k=0;k<num_connected;k++) {
			stream_info info(string("WiimoteMarkers") + boost::lexical_cast<string>(k),"Markers",1,IRREGULAR_RATE,cf_string,string("WiimoteMarkers") + boost::lexical_cast<string>(k) + boost::asio::ip::host_name());
			marker_outlets.push_back(boost::shared_ptr<stream_outlet>(new stream_outlet(info)));
		}

		// open an outlet for each Wiimote's sensor streams
		if (enable_sensors) {
			for (int k=0;k<num_connected;k++) {
				wiimote *wm = wiimotes[k];
				// enable motion sensing
				wiiuse_motion_sensing(wm,1);
				// enable infrared tracking
				wiiuse_set_ir(wm,1);
				// create outlet
				int num_channels = 3 + 5 + 3 + 3;		// (raw accel x/y/z, orient p/y/r/ap/ar, gforce x/y/z, deduced IR x/y/z)
				if (wm->exp.type == EXP_NUNCHUK)
					num_channels += 3 + 5 + 3 + 2;		// (raw accel x/y/z, orient p/y/r/ap/ar, gforce x/y/z, joystick ang/mag)
				if (wm->exp.type == EXP_CLASSIC)
					num_channels += 2 + 2 + 2;			// (joystick-left ang/mag, joystick-right ang/mag, left-shoulder-button-pressure, right-shoulder-button-pressure)
				if (wm->exp.type == EXP_GUITAR_HERO_3)
					num_channels += 2 + 1;				// (joystick ang/mag, whammy-bar)
				if (wm->exp.type == EXP_WII_BOARD)
					num_channels = 4;					// (weight-topleft,weight-topright,weight-bottomleft,weight-bottomright)
				stream_info info(string("WiimoteSensors")+=boost::lexical_cast<string>(k),"MoCap",num_channels,IRREGULAR_RATE,cf_float32,string("WiimoteSensors") + boost::lexical_cast<string>(k) + boost::asio::ip::host_name());

				// === physical setup meta-data ===
				xml_element setup = info.desc().append_child("setup");
				xml_element handset = setup.append_child("handset")
					.append_child_value("assigned_id",boost::lexical_cast<string>(wm->unid).c_str())
					.append_child_value("state",boost::lexical_cast<string>(wm->state).c_str())
					.append_child_value("battery_level",boost::lexical_cast<string>(wm->battery_level).c_str())
					.append_child_value("expansion",expansion_names[wm->exp.type]);
				xml_element ir_bar = setup.append_child("screen_tracking")
					.append_child_value("bar_placement",wm->ir.pos==WIIUSE_IR_ABOVE ? "AboveScreen" : "BelowScreen")
					.append_child_value("aspect",wm->ir.aspect==WIIUSE_ASPECT_4_3 ? "4:3" : "16:9")
					.append_child_value("state",boost::lexical_cast<string>(wm->ir.state).c_str());
				ir_bar.append_child("virtual_resolution")
					.append_child_value("X",boost::lexical_cast<string>(wm->ir.vres[0]).c_str())
					.append_child_value("Y",boost::lexical_cast<string>(wm->ir.vres[1]).c_str());
				ir_bar.append_child("correction_offset")
					.append_child_value("X",boost::lexical_cast<string>(wm->ir.offset[0]).c_str())
					.append_child_value("Y",boost::lexical_cast<string>(wm->ir.offset[1]).c_str());

				xml_element accel_calib = handset.append_child("accel_calib");
				accel_calib.append_child("cal_zero")
					.append_child_value("X",boost::lexical_cast<string>(wm->accel_calib.cal_zero.x).c_str())
					.append_child_value("Y",boost::lexical_cast<string>(wm->accel_calib.cal_zero.y).c_str())
					.append_child_value("Z",boost::lexical_cast<string>(wm->accel_calib.cal_zero.z).c_str());
				accel_calib.append_child("cal_g")
					.append_child_value("X",boost::lexical_cast<string>(wm->accel_calib.cal_g.x).c_str())
					.append_child_value("Y",boost::lexical_cast<string>(wm->accel_calib.cal_g.y).c_str())
					.append_child_value("Z",boost::lexical_cast<string>(wm->accel_calib.cal_g.z).c_str());
				accel_calib.append_child_value("smoothing_alpha",boost::lexical_cast<string>(wm->accel_calib.st_alpha).c_str());

				if (wm->exp.type == EXP_NUNCHUK) {
					xml_element nunchuk = setup.append_child("nunchuk");
					xml_element accel_calib = nunchuk.append_child("accel_calib");
					accel_calib.append_child("cal_zero")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.nunchuk.accel_calib.cal_zero.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.nunchuk.accel_calib.cal_zero.y).c_str())
						.append_child_value("Z",boost::lexical_cast<string>(wm->exp.nunchuk.accel_calib.cal_zero.z).c_str());
					accel_calib.append_child("cal_g")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.nunchuk.accel_calib.cal_g.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.nunchuk.accel_calib.cal_g.y).c_str())
						.append_child_value("Z",boost::lexical_cast<string>(wm->exp.nunchuk.accel_calib.cal_g.z).c_str());
					accel_calib.append_child_value("smoothing_alpha",boost::lexical_cast<string>(wm->exp.nunchuk.accel_calib.st_alpha).c_str());
					xml_element joystick_calib = nunchuk.append_child("joystick_calib");
					joystick_calib.append_child("min")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.nunchuk.js.min.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.nunchuk.js.min.y).c_str());
					joystick_calib.append_child("max")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.nunchuk.js.max.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.nunchuk.js.max.y).c_str());
					joystick_calib.append_child("center")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.nunchuk.js.center.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.nunchuk.js.center.y).c_str());
					nunchuk.append_child_value("orient_threshold",boost::lexical_cast<string>(wm->exp.nunchuk.orient_threshold).c_str());
					nunchuk.append_child_value("accel_threshold",boost::lexical_cast<string>(wm->exp.nunchuk.accel_threshold).c_str());
				}

				if (wm->exp.type == EXP_CLASSIC) {
					xml_element classic = setup.append_child("classic_controller");
					xml_element joyleft = classic.append_child("joystick_calib_left");
					joyleft.append_child("min")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.classic.ljs.min.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.classic.ljs.min.y).c_str());
					joyleft.append_child("max")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.classic.ljs.max.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.classic.ljs.max.y).c_str());
					joyleft.append_child("center")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.classic.ljs.center.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.classic.ljs.center.y).c_str());
					xml_element joyright = classic.append_child("joystick_calib_right");
					joyright.append_child("min")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.classic.rjs.min.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.classic.rjs.min.y).c_str());
					joyright.append_child("max")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.classic.rjs.max.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.classic.rjs.max.y).c_str());
					joyright.append_child("center")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.classic.rjs.center.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.classic.rjs.center.y).c_str());
				}

				if (wm->exp.type == EXP_GUITAR_HERO_3) {
					xml_element joystick_calib = setup.append_child("gh3_controller").append_child("joystick_calib");
					joystick_calib.append_child("min")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.gh3.js.min.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.gh3.js.min.y).c_str());
					joystick_calib.append_child("max")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.gh3.js.max.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.gh3.js.max.y).c_str());
					joystick_calib.append_child("center")
						.append_child_value("X",boost::lexical_cast<string>(wm->exp.gh3.js.center.x).c_str())
						.append_child_value("Y",boost::lexical_cast<string>(wm->exp.gh3.js.center.y).c_str());
				}

				if (wm->exp.type == EXP_WII_BOARD) {
					xml_element board_calib = setup.append_child("wiiboard").append_child("calib");
					board_calib.append_child("topleft")
						.append_child_value("A",boost::lexical_cast<string>(wm->exp.wb.ctl[0]).c_str())
						.append_child_value("B",boost::lexical_cast<string>(wm->exp.wb.ctl[1]).c_str())
						.append_child_value("C",boost::lexical_cast<string>(wm->exp.wb.ctl[2]).c_str());
					board_calib.append_child("topright")
						.append_child_value("A",boost::lexical_cast<string>(wm->exp.wb.ctr[0]).c_str())
						.append_child_value("B",boost::lexical_cast<string>(wm->exp.wb.ctr[1]).c_str())
						.append_child_value("C",boost::lexical_cast<string>(wm->exp.wb.ctr[2]).c_str());
					board_calib.append_child("bottomleft")
						.append_child_value("A",boost::lexical_cast<string>(wm->exp.wb.cbl[0]).c_str())
						.append_child_value("B",boost::lexical_cast<string>(wm->exp.wb.cbl[1]).c_str())
						.append_child_value("C",boost::lexical_cast<string>(wm->exp.wb.cbl[2]).c_str());
					board_calib.append_child("bottomright")
						.append_child_value("A",boost::lexical_cast<string>(wm->exp.wb.cbr[0]).c_str())
						.append_child_value("B",boost::lexical_cast<string>(wm->exp.wb.cbr[1]).c_str())
						.append_child_value("C",boost::lexical_cast<string>(wm->exp.wb.cbr[2]).c_str());
				}

				// channel layout
				lsl::xml_element channels = info.desc().append_child("channels");
				if (wm->exp.type == EXP_WII_BOARD) {
					// balance board channels
					channels.append_child("channel")
						.append_child_value("label","Weight_TopLeft")
						.append_child_value("type","Force")
						.append_child_value("unit","kilograms");
					channels.append_child("channel")
						.append_child_value("label","Weight_TopRight")
						.append_child_value("type","Force")
						.append_child_value("unit","kilograms");
					channels.append_child("channel")
						.append_child_value("label","Weight_BottomLeft")
						.append_child_value("type","Force")
						.append_child_value("unit","kilograms");
					channels.append_child("channel")
						.append_child_value("label","Weight_BottomRight")
						.append_child_value("type","Force")
						.append_child_value("unit","kilograms");
				} else {
					// otherwise we have first and foremost the Wiimote channels...
					channels.append_child("channel")
						.append_child_value("label","Wiimote_RawAccel_X")
						.append_child_value("type","Acceleration")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","raw");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_RawAccel_Y")
						.append_child_value("type","Acceleration")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","raw");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_RawAccel_Z")
						.append_child_value("type","Acceleration")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","raw");

					channels.append_child("channel")
						.append_child_value("label","Wiimote_Pitch")
						.append_child_value("type","Orientation")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","degrees");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_Yaw")
						.append_child_value("type","Orientation")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","degrees");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_Roll")
						.append_child_value("type","Orientation")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","degrees");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_AbsolutePitch")
						.append_child_value("type","Orientation")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","degrees");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_AbsoluteRoll")
						.append_child_value("type","Orientation")
						.append_child_value("device","Wiimote")
						.append_child_value("unit","degrees");

					channels.append_child("channel")
						.append_child_value("label","Wiimote_Gravity_X")
						.append_child_value("type","Acceleration")
						.append_child_value("device","Wiimote");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_Gravity_Y")
						.append_child_value("type","Acceleration")
						.append_child_value("device","Wiimote");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_Gravity_Z")
						.append_child_value("type","Acceleration")
						.append_child_value("device","Wiimote");

					channels.append_child("channel")
						.append_child_value("label","Wiimote_Pointing_X")
						.append_child_value("type","Direction")
						.append_child_value("device","Wiimote");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_Pointing_Y")
						.append_child_value("type","Direction")
						.append_child_value("device","Wiimote");
					channels.append_child("channel")
						.append_child_value("label","Wiimote_Pointing_Z")
						.append_child_value("type","Direction")
						.append_child_value("device","Wiimote");

					if (wm->exp.type == EXP_NUNCHUK) {
						// nunchuk extra channels
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_RawAccel_X")
							.append_child_value("type","Acceleration")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","raw");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_RawAccel_Y")
							.append_child_value("type","Acceleration")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","raw");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_RawAccel_Z")
							.append_child_value("type","Acceleration")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","raw");

						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Pitch")
							.append_child_value("type","Orientation")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Yaw")
							.append_child_value("type","Orientation")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Roll")
							.append_child_value("type","Orientation")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_AbsolutePitch")
							.append_child_value("type","Orientation")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_AbsoluteRoll")
							.append_child_value("type","Orientation")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","degrees");

						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Gravity_X")
							.append_child_value("type","Acceleration")
							.append_child_value("device","Nunchuk");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Gravity_Y")
							.append_child_value("type","Acceleration")
							.append_child_value("device","Nunchuk");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Gravity_Z")
							.append_child_value("type","Acceleration")
							.append_child_value("device","Nunchuk");

						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Joystick_Ang")
							.append_child_value("type","Direction")
							.append_child_value("device","Nunchuk")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","Nunchuk_Joystick_Mag")
							.append_child_value("type","Magnitude")
							.append_child_value("device","Nunchuk");
					}

					if (wm->exp.type == EXP_CLASSIC) {
						// classic controller extra channels
						channels.append_child("channel")
							.append_child_value("label","ClassicController_JoystickLeft_Ang")
							.append_child_value("type","Direction")
							.append_child_value("device","ClassicController")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","ClassicController_JoystickLeft_Mag")
							.append_child_value("type","Magnitude")
							.append_child_value("device","ClassicController");
						channels.append_child("channel")
							.append_child_value("label","ClassicController_JoystickRight_Ang")
							.append_child_value("type","Direction")
							.append_child_value("device","ClassicController")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","ClassicController_JoystickRight_Mag")
							.append_child_value("type","Magnitude")
							.append_child_value("device","ClassicController");

						channels.append_child("channel")
							.append_child_value("label","ClassicController_LeftShoulderButton")
							.append_child_value("type","Magnitude")
							.append_child_value("device","ClassicController");
						channels.append_child("channel")
							.append_child_value("label","ClassicController_RightShoulderButton")
							.append_child_value("type","Magnitude")
							.append_child_value("device","ClassicController");
					}

					if (wm->exp.type == EXP_GUITAR_HERO_3) {
						channels.append_child("channel")
							.append_child_value("label","GH3_Joystick_Ang")
							.append_child_value("type","Direction")
							.append_child_value("device","GH3")
							.append_child_value("unit","degrees");
						channels.append_child("channel")
							.append_child_value("label","GH3_Joystick_Mag")
							.append_child_value("type","Magnitude")
							.append_child_value("device","GH3");
						channels.append_child("channel")
							.append_child_value("label","GH3_WhammyBar")
							.append_child_value("type","Magnitude")
							.append_child_value("device","GH3");
					}
				}

				// misc information
				info.desc().append_child("acquisition")
					.append_child_value("manufacturer","Nintendo")
					.append_child_value("model","Wiimote")
					.append_child_value("api","wiiuse")
					.append_child_value("api_version",wiiuse_version());

				sensor_outlets.push_back(boost::shared_ptr<stream_outlet>(new stream_outlet(info)));
			}
		}

		// enter main loop
		cout << "Now transmitting data..." << endl;
		while (true) {
			if (wiiuse_poll(wiimotes,max_wiimotes)) {
				double now = local_clock();
				for (int i=0; i<num_connected; ++i) {
					wiimote *wm = wiimotes[i];
					switch (wm->event) {
					case WIIUSE_EVENT:
						// === check for button events that go into the marker streams ===

						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_TWO))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonTwo pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_TWO))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonTwo released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_ONE))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonTwo pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_ONE))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonOne released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_B))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonB pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_B))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonB released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_A))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonA pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_A))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonA released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_MINUS))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonMinus pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_MINUS))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonMinus released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_HOME))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonHome pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_HOME))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonHome released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_LEFT))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonLeft pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_LEFT))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonLeft released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_RIGHT))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonRight pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_RIGHT))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonLight released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_UP))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonUp pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_UP))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonUp released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_DOWN))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonDown pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_DOWN))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonDown released"),now);
						if (IS_JUST_PRESSED(wm,WIIMOTE_BUTTON_PLUS))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonPlus pressed"),now);
						if (IS_RELEASED(wm,WIIMOTE_BUTTON_PLUS))
							marker_outlets[i]->push_sample(vector<string>(1,"WiimoteButtonPlus released"),now);

						if (wm->exp.type == EXP_NUNCHUK) {
							if (IS_JUST_PRESSED((&(wm->exp.nunchuk)),NUNCHUK_BUTTON_C))
								marker_outlets[i]->push_sample(vector<string>(1,"NunchukButtonC pressed"),now);
							if (IS_RELEASED((&(wm->exp.nunchuk)),NUNCHUK_BUTTON_C))
								marker_outlets[i]->push_sample(vector<string>(1,"NunchukButtonC released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.nunchuk)),NUNCHUK_BUTTON_Z))
								marker_outlets[i]->push_sample(vector<string>(1,"NunchukButtonZ pressed"),now);
							if (IS_RELEASED((&(wm->exp.nunchuk)),NUNCHUK_BUTTON_Z))
								marker_outlets[i]->push_sample(vector<string>(1,"NunchukButtonZ released"),now);
						}

						if (wm->exp.type == EXP_CLASSIC) {
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_UP))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonUp pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_UP))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonUp released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_LEFT))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonLeft pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_LEFT))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonLeft released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_ZR))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonZR pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_ZR))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonZR released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_X))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonX pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_X))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonX released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_A))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonA pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_A))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonA released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_Y))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonY pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_Y))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonY released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_B))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonB pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_B))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonB released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_ZL))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonZL pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_ZL))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonZL released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_FULL_L))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonFullL pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_FULL_L))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonFullL released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_FULL_R))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonFullR pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_FULL_R))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonFullR released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_PLUS))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonPlus pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_PLUS))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonPlus released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_HOME))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonHome pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_HOME))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonHome released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_MINUS))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonMinus pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_MINUS))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonMinus released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_DOWN))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonDown pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_DOWN))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonDown released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_RIGHT))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonRight pressed"),now);
							if (IS_RELEASED((&(wm->exp.classic)),CLASSIC_CTRL_BUTTON_RIGHT))
								marker_outlets[i]->push_sample(vector<string>(1,"ClassicButtonRight released"),now);
						}

						if (wm->exp.type == EXP_GUITAR_HERO_3) {
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_STRUM_UP))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonStrumUp pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_STRUM_UP))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonStrumUp released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_YELLOW))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonYellow pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_YELLOW))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonYellow released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_GREEN))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonGreen pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_GREEN))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonGreen released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_BLUE))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonBlue pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_BLUE))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonBlue released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_RED))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonRed pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_RED))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonRed released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_ORANGE))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonOrange pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_ORANGE))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonOrange released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_PLUS))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonPlus pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_PLUS))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonPlus released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_MINUS))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonMinus pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_MINUS))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonMinus released"),now);
							if (IS_JUST_PRESSED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_STRUM_DOWN))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonStrumDown pressed"),now);
							if (IS_RELEASED((&(wm->exp.gh3)),GUITAR_HERO_3_BUTTON_STRUM_DOWN))
								marker_outlets[i]->push_sample(vector<string>(1,"GH3ButtonStrumDown released"),now);
						}

						// === construct the samples that go into the sensor streams ===
						if (enable_sensors) {
							if (wm->exp.type == EXP_WII_BOARD) {
								// balance board
								float sample[4] = {wm->exp.wb.tl, wm->exp.wb.tr, wm->exp.wb.bl, wm->exp.wb.br};
								sensor_outlets[i]->push_sample(sample,now);
							}
							if (wm->exp.type == EXP_NONE) {
								// Wiimote without expansions
								float sample[14] = {wm->accel.x, wm->accel.y, wm->accel.z,
									wm->orient.pitch,wm->orient.yaw,wm->orient.roll,wm->orient.a_pitch,wm->orient.a_roll,
									wm->gforce.x,wm->gforce.y,wm->gforce.z,
									wm->ir.x,wm->ir.y,wm->ir.z};
								sensor_outlets[i]->push_sample(sample,now);
							}
							if (wm->exp.type == EXP_NUNCHUK) {
								// Wiimote with Nunchuk
								float sample[27] = {wm->accel.x, wm->accel.y, wm->accel.z,
									wm->orient.pitch,wm->orient.yaw,wm->orient.roll,wm->orient.a_pitch,wm->orient.a_roll,
									wm->gforce.x,wm->gforce.y,wm->gforce.z,
									wm->ir.x,wm->ir.y,wm->ir.z,
									wm->exp.nunchuk.accel.x,wm->exp.nunchuk.accel.y,wm->exp.nunchuk.accel.z,
									wm->exp.nunchuk.orient.pitch,wm->exp.nunchuk.orient.yaw,wm->exp.nunchuk.orient.roll,wm->exp.nunchuk.orient.a_pitch,wm->exp.nunchuk.orient.a_roll,
									wm->exp.nunchuk.gforce.x,wm->exp.nunchuk.gforce.y,wm->exp.nunchuk.gforce.z,
									wm->exp.nunchuk.js.ang,wm->exp.nunchuk.js.mag};
								sensor_outlets[i]->push_sample(sample,now);
							}
							if (wm->exp.type == EXP_CLASSIC) {
								// Wiimote with classic controller
								float sample[20] = {wm->accel.x, wm->accel.y, wm->accel.z,
									wm->orient.pitch,wm->orient.yaw,wm->orient.roll,wm->orient.a_pitch,wm->orient.a_roll,
									wm->gforce.x,wm->gforce.y,wm->gforce.z,
									wm->ir.x,wm->ir.y,wm->ir.z,
									wm->exp.classic.ljs.ang,wm->exp.classic.ljs.mag,
									wm->exp.classic.rjs.ang,wm->exp.classic.rjs.mag,
									wm->exp.classic.l_shoulder,wm->exp.classic.r_shoulder};
								sensor_outlets[i]->push_sample(sample,now);
							}
							if (wm->exp.type == EXP_GUITAR_HERO_3) {
								// Wiimote with GH3 controller
								float sample[17] = {wm->accel.x, wm->accel.y, wm->accel.z,
									wm->orient.pitch,wm->orient.yaw,wm->orient.roll,wm->orient.a_pitch,wm->orient.a_roll,
									wm->gforce.x,wm->gforce.y,wm->gforce.z,
									wm->ir.x,wm->ir.y,wm->ir.z,
									wm->exp.gh3.js.ang,wm->exp.gh3.js.mag,
									wm->exp.gh3.whammy_bar};
								sensor_outlets[i]->push_sample(sample,now);
							}
						}
						break;

					case WIIUSE_DISCONNECT:
					case WIIUSE_UNEXPECTED_DISCONNECT:
						cout << "Warning: One of the Wiimotes was disconnected." << endl;
						break;
					case WIIUSE_NUNCHUK_INSERTED:
					case WIIUSE_CLASSIC_CTRL_INSERTED:
					case WIIUSE_WII_BOARD_CTRL_INSERTED:
					case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
						throw runtime_error("An expansion was inserted at runtime.");
					case WIIUSE_NUNCHUK_REMOVED:
					case WIIUSE_CLASSIC_CTRL_REMOVED:
					case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
					case WIIUSE_WII_BOARD_CTRL_REMOVED:
						throw runtime_error("An expansion was removed at runtime.");
					default:
						break;
					}
				}
			}
			boost::this_thread::yield();
		}
	}
	catch (std::runtime_error &e) {
		cerr << "Encountered an error: " << e.what() << endl;
	}
	wiiuse_cleanup(wiimotes,num_connected);

	return 0;
}

max_stars_repo_name: labstreaminglayer/App-Wiimote

max_issues_repo_name: labstreaminglayer/App-Wiimote

max_forks_repo_name: labstreaminglayer/App-Wiimote


text:
///////////////////////////////////////////////////////////////////////////////
// keeper_matcher.hpp
//
//  Copyright 2007 Eric Niebler. 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)

#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif

#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>

namespace boost { namespace xpressive { namespace detail
{

    ///////////////////////////////////////////////////////////////////////////////
    // keeper_matcher
    //  Xpr can be either a static_xpression, or a shared_matchable
    template<typename Xpr>
    struct keeper_matcher
      : quant_style<quant_variable_width, unknown_width::value, Xpr::pure>
    {
        keeper_matcher(Xpr const &xpr, bool pure = Xpr::pure)
          : xpr_(xpr)
          , pure_(pure)
        {
        }

        template<typename BidiIter, typename Next>
        bool match(match_state<BidiIter> &state, Next const &next) const
        {
            return Xpr::pure || this->pure_
              ? this->match_(state, next, mpl::true_())
              : this->match_(state, next, mpl::false_());
        }

        template<typename BidiIter, typename Next>
        bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
        {
            BidiIter const tmp = state.cur_;

            // matching xpr is guaranteed to not produce side-effects, don't bother saving state
            if(!this->xpr_.match(state))
            {
                return false;
            }
            else if(next.match(state))
            {
                return true;
            }

            state.cur_ = tmp;
            return false;
        }

        template<typename BidiIter, typename Next>
        bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
        {
            BidiIter const tmp = state.cur_;

            // matching xpr could produce side-effects, save state
            memento<BidiIter> mem = save_sub_matches(state);

            if(!this->xpr_.match(state))
            {
                reclaim_sub_matches(mem, state, false);
                return false;
            }
            else if(next.match(state))
            {
                reclaim_sub_matches(mem, state, true);
                return true;
            }

            restore_sub_matches(mem, state);
            state.cur_ = tmp;
            return false;
        }

        Xpr xpr_;
        bool pure_; // false if matching xpr_ could modify the sub-matches
    };

}}}

#endif

ext: hpp


text:
#include "osm_store.h"
#include <iostream>
#include <iterator>
#include <unordered_map>

#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_external_buffer.hpp>
#include <boost/interprocess/file_mapping.hpp>

#include <ciso646>
#include <boost/filesystem.hpp>
#include <boost/sort/sort.hpp>

using namespace std;
namespace bg = boost::geometry;

struct mmap_file
{
	std::string filename;

	std::mutex mutex;
	boost::interprocess::file_mapping mapping;
	boost::interprocess::mapped_region region;
	boost::interprocess::managed_external_buffer buffer;

	mmap_file(std::string const &filename, std::size_t offset = 0);
	~mmap_file();

	void remove();
};

using mmap_file_ptr = std::shared_ptr<mmap_file>;

struct mmap_dir_t
{
	static constexpr std::size_t increase = 1024000000;
	static constexpr std::size_t alignment = 32;

	std::string mmap_dir_filename;
	bool mmap_dir_created = false;

public:
	~mmap_dir_t();

	bool is_open();
	void open_mmap_file(std::string const &filename, size_t file_size = increase);
	void resize_mmap_file(size_t add_size);

	size_t mmap_file_size = 0;

	std::vector<mmap_file_ptr> files;
};

thread_local mmap_file_ptr mmap_file_thread_ptr;

struct mmap_shm
{
	std::mutex mutex;
	std::vector<uint8_t> region;
	boost::interprocess::managed_external_buffer buffer;

	static size_t mmap_file_size;

	mmap_shm(size_t size);

	static void open(size_t add_size);
	static void close();
};

using mmap_shm_ptr = std::shared_ptr<mmap_shm>;

using allocator_t = boost::interprocess::allocator<uint8_t, boost::interprocess::managed_external_buffer::segment_manager>;

static mmap_dir_t mmap_dir;

std::vector< mmap_shm_ptr > mmap_shm_regions;
size_t mmap_shm::mmap_file_size = 0;
thread_local mmap_shm_ptr mmap_shm_thread_region_ptr;

std::mutex mmap_allocator_mutex;

mmap_file::mmap_file(std::string const &filename, std::size_t offset)
	: mapping(filename.c_str(), boost::interprocess::read_write)
	, region(mapping, boost::interprocess::read_write)
	, buffer(boost::interprocess::create_only, reinterpret_cast<uint8_t *>(region.get_address()) + offset, region.get_size() - offset)
	, filename(filename)
{ }

mmap_file::~mmap_file()
{
	mapping = boost::interprocess::file_mapping();
	region = boost::interprocess::mapped_region();
	buffer = boost::interprocess::managed_external_buffer();

	remove();
}

void mmap_file::remove()
{
	if(!filename.empty()) {
		try {
			boost::filesystem::remove(filename.c_str());
		} catch(boost::filesystem::filesystem_error &e) {
			std::cout << e.what() << std::endl;
		}
	}
}

void mmap_dir_t::open_mmap_file(std::string const &dir_filename, size_t file_size)
{
	mmap_dir_filename = dir_filename;
	mmap_file_size = file_size;

	mmap_dir_created |= boost::filesystem::create_directory(dir_filename);

	std::string new_filename = mmap_dir_filename + "/mmap_" + to_string(mmap_dir.files.size()) + ".dat";
	std::cout << "Filename: " << new_filename << ", size: " << mmap_file_size << std::endl;
	if(boost::filesystem::ofstream(new_filename.c_str()).fail())
		throw std::runtime_error("Failed to open mmap file");
	boost::filesystem::resize_file(new_filename.c_str(), 0);
	boost::filesystem::resize_file(new_filename.c_str(), mmap_file_size);
	mmap_file_thread_ptr = std::make_shared<mmap_file>(new_filename.c_str());

	mmap_dir.files.emplace_back(mmap_file_thread_ptr);
}

void mmap_dir_t::resize_mmap_file(size_t add_size)
{
	auto offset = mmap_file_size;
	auto size = increase + (add_size + alignment) - (add_size % alignment);

	std::string new_filename = mmap_dir_filename + "/mmap_" + to_string(mmap_dir.files.size()) + ".dat";
	if(boost::filesystem::ofstream(new_filename.c_str()).fail())
		throw std::runtime_error("Failed to open mmap file");
	boost::filesystem::resize_file(new_filename.c_str(), size);
	mmap_file_thread_ptr = std::make_shared<mmap_file>(new_filename.c_str(), 0);

	mmap_dir.files.emplace_back(mmap_file_thread_ptr);
	mmap_file_size = offset + size;
}

bool mmap_dir_t::is_open()
{
	return !mmap_dir.files.empty();
}

 mmap_dir_t::~mmap_dir_t()
{
	if(!mmap_dir_filename.empty()) {
		try {
			files.clear();

			if(mmap_dir_created) {
				boost::filesystem::remove(mmap_dir_filename.c_str());
			}
		} catch(boost::filesystem::filesystem_error &e) {
			std::cout << e.what() << std::endl;
		}
	}
}

mmap_shm::mmap_shm(size_t size)
	: region(size)
	, buffer(boost::interprocess::create_only, region.data(), region.size())
{ }

void mmap_shm::open(size_t add_size)
{
	constexpr std::size_t increase = 64000000;
	constexpr std::size_t alignment = 32;

	auto size = increase + (add_size + alignment) - (add_size % alignment);
	mmap_shm_thread_region_ptr = std::make_shared<mmap_shm>(size);
	mmap_shm_regions.emplace_back(mmap_shm_thread_region_ptr);
	mmap_file_size += size;
}

void mmap_shm::close()
{
	mmap_shm_regions.clear();
	mmap_shm_thread_region_ptr.reset();
}

bool void_mmap_allocator_shutdown = false;

void void_mmap_allocator::shutdown() { void_mmap_allocator_shutdown = true; }

void * void_mmap_allocator::allocate(size_type n, const void *hint)
{
	while(true) {
		try {
			if(mmap_dir.is_open() && mmap_file_thread_ptr != nullptr) {
				auto &i = *mmap_file_thread_ptr;
				std::lock_guard<std::mutex> lock(i.mutex);
				allocator_t allocator(i.buffer.get_segment_manager());
				return &(*allocator.allocate(n, hint));
			} else if(mmap_shm_thread_region_ptr != nullptr) {
				auto &i = *mmap_shm_thread_region_ptr;
				std::lock_guard<std::mutex> lock(i.mutex);
				allocator_t allocator(i.buffer.get_segment_manager());
				return &(*allocator.allocate(n, hint));
			}
		} catch(boost::interprocess::bad_alloc &e) {
			// This mmap file is full
		}

		std::lock_guard<std::mutex> lock(mmap_allocator_mutex);
		if(mmap_dir.is_open())
			mmap_dir.resize_mmap_file(n);
		else
			mmap_shm::open(n);
	}
}

void void_mmap_allocator::deallocate(void *p, size_type n)
{
	destroy(p);
}

void void_mmap_allocator::destroy(void *p)
{
	if(void_mmap_allocator_shutdown) return;

	if(mmap_shm_thread_region_ptr != nullptr) {
		auto &i = *mmap_shm_thread_region_ptr;
		if(p >= (void const *)i.region.data()  && p < reinterpret_cast<void const *>(reinterpret_cast<uint8_t const *>(i.region.data()) + i.region.size())) {
			allocator_t allocator(i.buffer.get_segment_manager());
			return allocator.destroy(reinterpret_cast<uint8_t *>(p));
		}
	}

	if(mmap_file_thread_ptr != nullptr) {
		auto &i = *mmap_file_thread_ptr;
		if(p >= i.region.get_address()  && p < reinterpret_cast<void const *>(reinterpret_cast<uint8_t const *>(i.region.get_address()) + i.region.get_size())) {
			allocator_t allocator(i.buffer.get_segment_manager());
			allocator.destroy(reinterpret_cast<uint8_t *>(p));
			return;
		}
	}

	std::lock_guard<std::mutex> lock(mmap_allocator_mutex);
	for(auto &i: mmap_shm_regions) {
		if(p >= (void const *)i->region.data()  && p < reinterpret_cast<void const *>(reinterpret_cast<uint8_t const *>(i->region.data()) + i->region.size())) {
			std::lock_guard<std::mutex> lock(i->mutex);
			allocator_t allocator(i->buffer.get_segment_manager());
			allocator.destroy(reinterpret_cast<uint8_t *>(p));
			return;
		}
	}

	for(auto &i: mmap_dir.files) {
		if(p >= i->region.get_address()  && p < reinterpret_cast<void const *>(reinterpret_cast<uint8_t const *>(i->region.get_address()) + i->region.get_size())) {
			std::lock_guard<std::mutex> lock(i->mutex);
			allocator_t allocator(i->buffer.get_segment_manager());
			allocator.destroy(reinterpret_cast<uint8_t *>(p));
			return;
		}
	}
}

void NodeStore::sort(unsigned int threadNum) {
	std::lock_guard<std::mutex> lock(mutex);
	boost::sort::block_indirect_sort(
		mLatpLons->begin(), mLatpLons->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; },
		threadNum);
}

void WayStore::sort(unsigned int threadNum) {
	std::lock_guard<std::mutex> lock(mutex);
	boost::sort::block_indirect_sort(
		mNodeLists->begin(), mNodeLists->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; },
		threadNum);
}

static inline bool isClosed(WayStore::nodeid_vector_t const &way) {
	return way.begin() == way.end();
}

void OSMStore::open(std::string const &osm_store_filename)
{
	mmap_dir.open_mmap_file(osm_store_filename);
	reopen();
	mmap_shm::close();
}

void OSMStore::shapes_sort(unsigned int threadNum)
{
	std::cout << "Sorting loaded shapes" << std::endl;
	boost::sort::block_indirect_sort(
		shp_generated.points_store->begin(), shp_generated.points_store->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; }, threadNum);
	boost::sort::block_indirect_sort(
		shp_generated.linestring_store->begin(), shp_generated.linestring_store->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; },
		threadNum);
	boost::sort::block_indirect_sort(
		shp_generated.multi_polygon_store->begin(), shp_generated.multi_polygon_store->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; },
		threadNum);
}

void OSMStore::generated_sort(unsigned int threadNum)
{
	std::cout << "Sorting generated geometries" << std::endl;
	std::lock_guard<std::mutex> lock_points(osm_generated.points_store_mutex);
	boost::sort::block_indirect_sort(
		osm_generated.points_store->begin(), osm_generated.points_store->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; }, threadNum);

	std::lock_guard<std::mutex> lock_linestring(osm_generated.linestring_store_mutex);
	boost::sort::block_indirect_sort(
		osm_generated.linestring_store->begin(), osm_generated.linestring_store->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; },
		threadNum);

	std::lock_guard<std::mutex> lock_multi_linestring(osm_generated.multi_linestring_store_mutex);
	boost::sort::block_indirect_sort(
		osm_generated.multi_linestring_store->begin(), osm_generated.multi_linestring_store->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; },
		threadNum);

	std::lock_guard<std::mutex> lock_multi_polygon(osm_generated.multi_polygon_store_mutex);
	boost::sort::block_indirect_sort(
		osm_generated.multi_polygon_store->begin(), osm_generated.multi_polygon_store->end(),
		[](auto const &a, auto const &b) { return a.first < b.first; },
		threadNum);
}

void OSMStore::nodes_sort(unsigned int threadNum)
{
	std::cout << "\nSorting nodes" << std::endl;
	if(!use_compact_nodes)
		nodes.sort(threadNum);
}

void OSMStore::ways_sort(unsigned int threadNum) {
	std::cout << "\nSorting ways" << std::endl;
	ways.sort(threadNum);
}

MultiPolygon OSMStore::wayListMultiPolygon(WayVec::const_iterator outerBegin, WayVec::const_iterator outerEnd, WayVec::const_iterator innerBegin, WayVec::const_iterator innerEnd) const {
	MultiPolygon mp;
	if (outerBegin == outerEnd) { return mp; } // no outers so quit

	std::vector<NodeDeque> outers;
	std::vector<NodeDeque> inners;
	std::map<WayID,bool> done; // true=this way has already been added to outers/inners, don't reconsider

	// merge constituent ways together
	mergeMultiPolygonWays(outers, done, outerBegin, outerEnd);
	mergeMultiPolygonWays(inners, done, innerBegin, innerEnd);

	// add all inners and outers to the multipolygon
	std::vector<Ring> filledInners;
	for (auto it = inners.begin(); it != inners.end(); ++it) {
		Ring inner;
		fillPoints(inner, it->begin(), it->end());
		filledInners.emplace_back(inner);
	}
	bool onlyOneOuter = outers.size()==1;
	for (auto ot = outers.begin(); ot != outers.end(); ot++) {
		Polygon poly;
		fillPoints(poly.outer(), ot->begin(), ot->end());
		for (auto it = filledInners.begin(); it != filledInners.end(); ++it) {
			if (onlyOneOuter || geom::within(*it, poly.outer())) { poly.inners().emplace_back(*it); }
		}
		mp.emplace_back(move(poly));
	}

	// fix winding
	geom::correct(mp);
	return mp;
}

MultiLinestring OSMStore::wayListMultiLinestring(WayVec::const_iterator outerBegin, WayVec::const_iterator outerEnd) const {
	MultiLinestring mls;
	if (outerBegin == outerEnd) { return mls; }

	std::vector<NodeDeque> linestrings;
	std::map<WayID,bool> done;

	mergeMultiPolygonWays(linestrings, done, outerBegin, outerEnd);

	for (auto ot = linestrings.begin(); ot != linestrings.end(); ot++) {
		Linestring ls;
		fillPoints(ls, ot->begin(), ot->end());
		mls.emplace_back(move(ls));
	}

	return mls;
}

// Assemble multipolygon constituent ways
// - Any closed polygons are added as-is
// - Linestrings are joined to existing linestrings with which they share a start/end
// - If no matches can be found, then one linestring is added (to 'attract' others)
// - The process is rerun until no ways are left
// There's quite a lot of copying going on here - could potentially be addressed
void OSMStore::mergeMultiPolygonWays(std::vector<NodeDeque> &results, std::map<WayID,bool> &done, WayVec::const_iterator itBegin, WayVec::const_iterator itEnd) const {

	// Create maps of start/end nodes
	std::unordered_map<NodeID, std::vector<NodeID>> startNodes;
	std::unordered_map<NodeID, std::vector<NodeID>> endNodes;
	for (auto it = itBegin; it != itEnd; ++it) {
		if (done[*it]) { continue; }
		try {
			auto const &way = ways.at(*it);
			if (isClosed(way) || results.empty()) {
				// if start==end, simply add it to the set
				results.emplace_back(way.begin(), way.end());
				done[*it] = true;
			} else {
				startNodes[way.front()].emplace_back(*it);
				endNodes[way.back()].emplace_back(*it);
			}
		} catch (std::out_of_range &err) {
			if (verbose) { cerr << "Missing way in relation: " << err.what() << endl; }
			done[*it] = true;
		}
	}

	auto deleteFromWayList = [&](NodeID n, NodeID w, bool which) {
		auto &nodemap = which ? startNodes : endNodes;
		std::vector<NodeID> &waylist = nodemap.find(n)->second;
		waylist.erase(std::remove(waylist.begin(), waylist.end(), w), waylist.end());
		if (waylist.empty()) { nodemap.erase(nodemap.find(n)); }
	};
	auto removeWay = [&](NodeID w) {
		auto const &way = ways.at(w);
		NodeID first = way.front();
		NodeID last  = way.back();
		if (startNodes.find(first) != startNodes.end()) { deleteFromWayList(first, w, true ); }
		if (startNodes.find(last)  != startNodes.end()) { deleteFromWayList(last,  w, true ); }
		if (endNodes.find(first)   != endNodes.end()  ) { deleteFromWayList(first, w, false); }
		if (endNodes.find(last)    != endNodes.end()  ) { deleteFromWayList(last,  w, false); }
		done[w] = true;
	};

	// Loop through, repeatedly adding start/end nodes if we can
	int added;
	do {
		added = 0;
		for (auto rt = results.begin(); rt != results.end(); rt++) {
			bool working=true;
			do {
				NodeID rFirst = rt->front();
				NodeID rLast  = rt->back();
				if (rFirst==rLast) break;
				if (startNodes.find(rLast)!=startNodes.end()) {
					// append to the result
					auto match = startNodes.find(rLast)->second;
					auto nodes = ways.at(match.back());
					rt->insert(rt->end(), nodes.begin(), nodes.end());
					removeWay(match.back());
					added++;

				} else if (endNodes.find(rLast)!=endNodes.end()) {
					// append reversed to the original
					auto match = endNodes.find(rLast)->second;
					auto nodes = ways.at(match.back());
					rt->insert(rt->end(),
						std::make_reverse_iterator(nodes.end()),
						std::make_reverse_iterator(nodes.begin()));
					removeWay(match.back());
					added++;

				} else if (endNodes.find(rFirst)!=endNodes.end()) {
					// prepend to the original
					auto match = endNodes.find(rFirst)->second;
					auto nodes = ways.at(match.back());
					rt->insert(rt->begin(), nodes.begin(), nodes.end());
					removeWay(match.back());
					added++;

				} else if (startNodes.find(rFirst)!=startNodes.end()) {
					// prepend reversed to the original
					auto match = startNodes.find(rFirst)->second;
					auto nodes = ways.at(match.back());
					rt->insert(rt->begin(),
						std::make_reverse_iterator(nodes.end()),
						std::make_reverse_iterator(nodes.begin()));
					removeWay(match.back());
					added++;

				} else { working=false; }

			} while (working);
		}

		// If nothing was added, then 'seed' it with a remaining unallocated way
		for (int i=0; i<=1; i++) {
			if (added>0) continue;
			for (auto nt : (i==0 ? startNodes : endNodes)) {
				NodeID w = nt.second.back();
				auto const &way = ways.at(w);
				results.emplace_back(way.begin(), way.end());
				added++;
				removeWay(w);
				break;
			}
		}
	} while (added>0);
};

void OSMStore::reportStoreSize(std::ostringstream &str) {
	if (mmap_dir.mmap_file_size>0) { str << "Store size " << (mmap_dir.mmap_file_size / 1000000000) << "G | "; }
}

void OSMStore::reportSize() const {
	std::cout << "Stored " << nodes.size() << " nodes, " << ways.size() << " ways, " << relations.size() << " relations" << std::endl;
	std::cout << "Shape points: " << shp_generated.points_store->size() << ", lines: " << shp_generated.linestring_store->size() << ", polygons: " << shp_generated.multi_polygon_store->size() << std::endl;
	std::cout << "Generated points: " << osm_generated.points_store->size() << ", lines: " << osm_generated.linestring_store->size() << ", polygons: " << osm_generated.multi_polygon_store->size() << std::endl;
}

ext: cpp

max_stars_repo_name: yuiseki/tilemaker

max_issues_repo_name: yuiseki/tilemaker

max_forks_repo_name: yuiseki/tilemaker


text:
//=====================================================================//
/*!	@file
	@brief	AAC ファイルを扱うクラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/glfw_app/blob/master/LICENSE
*/
//=====================================================================//
#include "aac_io.hpp"
#include "pcm.hpp"
#include <cstring>
#include <cstdio>
#include "img_io/img_files.hpp"
#include "img_io/img_utils.hpp"
#include <boost/format.hpp>

namespace al {

	// make this higher to support files with more channels
	static const int MAX_CHANNELS = 6;

	// FAAD file buffering routines
	struct aac_buffer {
		utils::file_io&	fin;
		long	bytes_into_buffer;
		long	bytes_consumed;
		long	file_offset;
		unsigned char*	buffer;
		int	at_eof;
		aac_buffer(utils::file_io& fin_) : fin(fin_), bytes_into_buffer(0),
		  bytes_consumed(0), file_offset(0), buffer(0),
		  at_eof(0) { }
	};

	static int fill_buffer_(aac_buffer& b)
	{
		int bread;

		if (b.bytes_consumed > 0) {
			if (b.bytes_into_buffer) {
				memmove((void*)b.buffer, (void*)(b.buffer + b.bytes_consumed),
					b.bytes_into_buffer * sizeof(unsigned char));
			}

			if (!b.at_eof) {
				bread = b.fin.read(b.buffer + b.bytes_into_buffer, 1, b.bytes_consumed);

				if (bread != b.bytes_consumed) b.at_eof = 1;

				b.bytes_into_buffer += bread;
			}

			b.bytes_consumed = 0;

			if (b.bytes_into_buffer > 3) {
				if (memcmp(b.buffer, "TAG", 3) == 0) b.bytes_into_buffer = 0;
			}
			if (b.bytes_into_buffer > 11) {
				if (memcmp(b.buffer, "LYRICSBEGIN", 11) == 0) b.bytes_into_buffer = 0;
			}
			if (b.bytes_into_buffer > 8) {
				if (memcmp(b.buffer, "APETAGEX", 8) == 0) b.bytes_into_buffer = 0;
			}
		}
		return 1;
	}

	static void advance_buffer_(aac_buffer& b, int bytes)
	{
		b.file_offset += bytes;
		b.bytes_consumed = bytes;
		b.bytes_into_buffer -= bytes;
		if (b.bytes_into_buffer < 0) b.bytes_into_buffer = 0;
	}

	static const int adts_sample_rates_[] = {
		96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0
	};

	static int adts_parse_(aac_buffer& b, int *bitrate, float *length)
	{
		int frames, frame_length;
		int t_framelength = 0;
		int samplerate;
		float frames_per_sec, bytes_per_frame;

		/* Read all frames to ensure correct time and bitrate */
		for (frames = 0; /* */; frames++) {
			fill_buffer_(b);

			if (b.bytes_into_buffer > 7) {
            	/* check syncword */
				if (!((b.buffer[0] == 0xFF)&&((b.buffer[1] & 0xF6) == 0xF0))) break;

				if (frames == 0) {
					samplerate = adts_sample_rates_[(b.buffer[2] & 0x3c) >> 2];
				}

				frame_length = ((((unsigned int)b.buffer[3] & 0x3)) << 11)
					| (((unsigned int)b.buffer[4]) << 3) | (b.buffer[5] >> 5);

				t_framelength += frame_length;

				if (frame_length > b.bytes_into_buffer) break;

				advance_buffer_(b, frame_length);
			} else {
				break;
			}
		}

		frames_per_sec = (float)samplerate / 1024.0f;
		if (frames != 0) {
			bytes_per_frame = (float)t_framelength / (float)(frames*1000);
		} else {
			bytes_per_frame = 0;
		}
		*bitrate = (int)(8. * bytes_per_frame * frames_per_sec + 0.5);
		if (frames_per_sec != 0) {
			*length = (float)frames / frames_per_sec;
		} else {
			*length = 1;
		}

		return 1;
	}

#if 0
	static int FindAdtsSRIndex_(int sr)
	{
		for (int i = 0; i < 16; i++) {
			if (sr == adts_sample_rates_[i]) return i;
		}
		return 16 - 1;
	}

	static unsigned char *MakeAdtsHeader_(int *dataSize,
		NeAACDecFrameInfo *hInfo, int old_format)
	{
		unsigned char *data;
		int profile = (hInfo->object_type - 1) & 0x3;
		int sr_index = ((hInfo->sbr == SBR_UPSAMPLED) || (hInfo->sbr == NO_SBR_UPSAMPLED)) ?
        	FindAdtsSRIndex_(hInfo->samplerate / 2) : FindAdtsSRIndex_(hInfo->samplerate);
		int skip = (old_format) ? 8 : 7;
		int framesize = skip + hInfo->bytesconsumed;

		if (hInfo->header_type == ADTS) framesize -= skip;

		*dataSize = 7;

		data = (unsigned char*)malloc(*dataSize * sizeof(unsigned char));
		memset(data, 0, *dataSize * sizeof(unsigned char));

		data[0] += 0xFF; /* 8b: syncword */

		data[1] += 0xF0; /* 4b: syncword */
		/* 1b: mpeg id = 0 */
		/* 2b: layer = 0 */
		data[1] += 1; /* 1b: protection absent */

		data[2] += ((profile << 6) & 0xC0); /* 2b: profile */
		data[2] += ((sr_index << 2) & 0x3C); /* 4b: sampling_frequency_index */
		/* 1b: private = 0 */
		data[2] += ((hInfo->channels >> 2) & 0x1); /* 1b: channel_configuration */

		data[3] += ((hInfo->channels << 6) & 0xC0); /* 2b: channel_configuration */
		/* 1b: original */
		/* 1b: home */
		/* 1b: copyright_id */
		/* 1b: copyright_id_start */
		data[3] += ((framesize >> 11) & 0x3); /* 2b: aac_frame_length */

		data[4] += ((framesize >> 3) & 0xFF); /* 8b: aac_frame_length */

		data[5] += ((framesize << 5) & 0xE0); /* 3b: aac_frame_length */
		data[5] += ((0x7FF >> 6) & 0x1F); /* 5b: adts_buffer_fullness */

		data[6] += ((0x7FF << 2) & 0x3F); /* 6b: adts_buffer_fullness */
		/* 2b: num_raw_data_blocks */

		return data;
	}
#endif

	static audio decode_aac_file_(utils::file_io& fin)
	{
		int old_format = 0;
		int outputFormat = FAAD_FMT_16BIT;
		int object_type = LC;
		int downMatrix = 0;
		int def_srate = 0;

		int tagsize;
		unsigned long samplerate;
		unsigned char channels;
		void *sample_buffer;

		NeAACDecHandle hDecoder;
		NeAACDecFrameInfo frameInfo;
		NeAACDecConfigurationPtr config;

		char percents[200];
		int percent, old_percent = -1;
		int bread, fileread;
		int header_type = 0;
		int bitrate = 0;
		float length = 0;

///		int first_time = 1;

		aac_buffer b(fin);

		fileread = b.fin.get_file_size();

		if (!(b.buffer = (unsigned char*)malloc(FAAD_MIN_STREAMSIZE * MAX_CHANNELS))) {
			/// std::cerr << "Memory allocation error\n";
			return 0;
		}
		memset(b.buffer, 0, FAAD_MIN_STREAMSIZE * MAX_CHANNELS);

		bread = b.fin.read(b.buffer, 1, FAAD_MIN_STREAMSIZE * MAX_CHANNELS);
		b.bytes_into_buffer = bread;
		b.bytes_consumed = 0;
		b.file_offset = 0;

		if (bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS) b.at_eof = 1;

		tagsize = 0;
		if (!memcmp(b.buffer, "ID3", 3)) {
	        /* high bit is not used */
			tagsize = (b.buffer[6] << 21) | (b.buffer[7] << 14) |
				(b.buffer[8] <<  7) | (b.buffer[9] <<  0);

			tagsize += 10;
			advance_buffer_(b, tagsize);
			fill_buffer_(b);
		}

		hDecoder = NeAACDecOpen();

		/* Set the default object type and samplerate */
		/* This is useful for RAW AAC files */
		config = NeAACDecGetCurrentConfiguration(hDecoder);
		if (def_srate) {
			config->defSampleRate = def_srate;
		}
		config->defObjectType = object_type;
		config->outputFormat = outputFormat;
		config->downMatrix = downMatrix;
		config->useOldADTSFormat = old_format;
		//config->dontUpSampleImplicitSBR = 1;
		NeAACDecSetConfiguration(hDecoder, config);

		/* get AAC infos for printing */
		header_type = 0;
		if ((b.buffer[0] == 0xFF) && ((b.buffer[1] & 0xF6) == 0xF0)) {
			adts_parse_(b, &bitrate, &length);
			b.fin.seek(tagsize, utils::file_io::seek::set);

			bread = b.fin.read(b.buffer, 1, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
			if (bread != FAAD_MIN_STREAMSIZE * MAX_CHANNELS) b.at_eof = 1;
			else b.at_eof = 0;
			b.bytes_into_buffer = bread;
			b.bytes_consumed = 0;
			b.file_offset = tagsize;

			header_type = 1;
		} else if (memcmp(b.buffer, "ADIF", 4) == 0) {
			int skip_size = (b.buffer[4] & 0x80) ? 9 : 0;
			bitrate = ((unsigned int)(b.buffer[4 + skip_size] & 0x0F)<<19) |
				((unsigned int)b.buffer[5 + skip_size]<<11) |
				((unsigned int)b.buffer[6 + skip_size]<<3) |
				((unsigned int)b.buffer[7 + skip_size] & 0xE0);

			length = (float)fileread;
			if (length != 0) {
				length = ((float)length*8.f) / ((float)bitrate) + 0.5f;
			}

			bitrate = (int)((float)bitrate / 1000.0f + 0.5f);

			header_type = 2;
		}

///    *song_length = length;

		fill_buffer_(b);
		if ((bread = NeAACDecInit(hDecoder, b.buffer,
			b.bytes_into_buffer, &samplerate, &channels)) < 0) {
			/* If some error initializing occured, skip the file */
			std::cerr << "Error initializing decoder library.\n";
            free(b.buffer);
			NeAACDecClose(hDecoder);
			return 0;
		}
		advance_buffer_(b, bread);
		fill_buffer_(b);

#if 0
		/* print AAC file info */
		std::cerr << aacfile << " file info:\n";
		switch (header_type) {
		case 0:
			std::cerr << "RAW\n\n";
		break;
		case 1:
			std::cerr << boost::format("ADTS, %.3f sec, %d kbps, %d Hz\n\n")
				% length % bitrate % samplerate;
		break;
		case 2:
			std::cerr << boost::format("ADIF, %.3f sec, %d kbps, %d Hz\n\n")
				% length % bitrate % samplerate;
		break;
		}
#endif

		do {
			sample_buffer = NeAACDecDecode(hDecoder, &frameInfo,
				b.buffer, b.bytes_into_buffer);

			/* update buffer indices */
			advance_buffer_(b, frameInfo.bytesconsumed);

			if (frameInfo.error > 0) {
				std::cerr << "Error: " << NeAACDecGetErrorMessage(frameInfo.error) << std::endl;
			}

			percent = std::min(static_cast<int>((b.file_offset * 100) / fileread), 100);
			if (percent > old_percent) {
				old_percent = percent;
				/// std::cerr << boost::format("%d%% decoding %s.") % percent % aacfile;
				std::cerr << boost::format("%s\r") % percents;
			}

			if ((frameInfo.error == 0) && (frameInfo.samples > 0)) {
				/// if (write_audio_file(aufile, sample_buffer, frameInfo.samples, 0) == 0)
                /// break;
			}

			/* fill buffer */
			fill_buffer_(b);

			/* to make sure it stops now */
			if (b.bytes_into_buffer == 0) sample_buffer = NULL;

		} while (sample_buffer != NULL);

		NeAACDecClose(hDecoder);

		free(b.buffer);

//		return frameInfo.error;
		return 0;
	}

	static uint32_t read_callback_(void* user_data, void* buffer, uint32_t length)
	{
		utils::file_io* fin = static_cast<utils::file_io*>(user_data);
		if(fin) return fin->read(buffer, 1, length);
		return 0;
	}

	static uint32_t seek_callback_(void* user_data, uint64_t position)
	{
		utils::file_io* fin = static_cast<utils::file_io*>(user_data);
		if(fin) return fin->seek(position, utils::file_io::seek::set);
		else return 0;
	}

	static int get_aac_track_(mp4ff_t *infile)
	{
		/* find AAC track */
		int numTracks = mp4ff_total_tracks(infile);

		for(int i = 0; i < numTracks; i++) {
			unsigned char *buff = NULL;
			unsigned int buff_size = 0;
			mp4AudioSpecificConfig mp4ASC;

			mp4ff_get_decoder_config(infile, i, &buff, &buff_size);

			if (buff) {
				int rc = NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC);
				free(buff);

				if (rc < 0) continue;
				return i;
			}
		}

		/* can't decode this */
		return -1;
	}

#if 0
	static void list_mp4(mp4ff_t* infile, mp4AudioSpecificConfig& mp4ASC, int track)
	{
       	static const char* ot[] = {
			"NULL", "MAIN AAC", "LC AAC", "SSR AAC", "LTP AAC", "HE AAC"
		};
		long samples = mp4ff_num_samples(infile, track);
		float f = 1024.0f;
		float seconds;
		if (mp4ASC.sbr_present_flag == 1) {
			f = f * 2.0;
		}
		seconds = (float)samples * (float)(f - 1.0f) / (float)mp4ASC.samplingFrequency;

		std::cout << boost::format("%s\t%.3f secs, %d ch, %d Hz\n\n")
			% (ot[(mp4ASC.objectTypeIndex > 5) ? 0 : mp4ASC.objectTypeIndex])
			% seconds % mp4ASC.channelsConfiguration % mp4ASC.samplingFrequency;

#define PRINT_MP4_METADATA
#ifdef PRINT_MP4_METADATA
///		char *tag = 0;
///		char *item = 0;
		int j = mp4ff_meta_get_num_items(infile);
		for(int k = 0; k < j; k++) {
			char* item;
			char* value;
			if(mp4ff_meta_get_by_index(infile, k, &item, &value)) {
   				if(std::string(item) == "cover") {
	   				size_t size = mp4ff_meta_get_item_size(infile, k);
	   				std::cout << boost::format("%s: (%d)\n") % item % size;
	   			} else {
	   				std::cout << boost::format("%s: %s\n") % item % value;
	   			}
				mp4ff_meta_free(infile, item, value);
   			}
		}
		if (j > 0) std::cout << std::endl;
#endif
	}
#endif

	void aac_io::destroy_mp4_(decode_mp4_t& dt)
	{
		mp4ff_close(dt.infile);
		NeAACDecClose(dt.h_decoder);
	}

	bool aac_io::decode_audio_mp4_(decode_mp4_t& dt, uint32_t idx)
	{
		long dur = mp4ff_get_sample_duration(dt.infile, dt.track, idx);
		unsigned char* tmp = 0;
		uint32_t size = 0;
		int rc = mp4ff_read_sample(dt.infile, dt.track, idx, &tmp, &size);
		if(rc == 0) {
			dt.tmp = 0;
			return false;
		}

		dt.sample = NeAACDecDecode(dt.h_decoder, &dt.frame_info, tmp, size);
		dt.tmp = tmp;

		if(!dt.no_gapless) {
			if(idx == 0) dur = 0;

			if(dt.useAacLength || (dt.timescale != dt.samplerate)) {
				dt.count = dt.frame_info.samples;
			} else {
				dt.count = (unsigned int)(dur * dt.frame_info.channels);
				if(dt.count > dt.frame_info.samples) {
					dt.count = dt.frame_info.samples;
				}

				if(!dt.useAacLength && !dt.initial && (idx < dt.samples / 2)
				  && (dt.count != dt.frame_info.samples)) {
					std::cout << "MP4 seems to have incorrect frame duration, using values from AAC data.\n";
					dt.useAacLength = 1;
					dt.count = dt.frame_info.samples;
				}
			}

			if(dt.initial && (dt.count < dt.framesize * dt.frame_info.channels)
			  && (dt.frame_info.samples > dt.count)) {
				dt.delay = dt.frame_info.samples - dt.count;
			}
		} else {
			dt.count = dt.frame_info.samples;
		}

		if(dt.count > 0) dt.initial = true;

		return true;
	}

	bool aac_io::decode_track_mp4_(utils::file_io& fin, decode_mp4_t& dt)
	{
		dt.h_decoder = NeAACDecOpen();

		// Set configuration
		dt.config = NeAACDecGetCurrentConfiguration(dt.h_decoder);
		dt.config->outputFormat = FAAD_FMT_16BIT;
		dt.config->downMatrix   = 0;
		//config->dontUpSampleImplicitSBR = 1;
		NeAACDecSetConfiguration(dt.h_decoder, dt.config);

		dt.mp4cb.read = read_callback_;
		dt.mp4cb.seek = seek_callback_;
		dt.mp4cb.user_data = &fin;
		dt.infile = mp4ff_open_read(&dt.mp4cb);
		if(dt.infile == 0) {
			NeAACDecClose(dt.h_decoder);
			return false;
		}

		dt.track = get_aac_track_(dt.infile);
		if(dt.track < 0) {
///			std::cout << "Unable to find correct AAC sound track in the MP4 file.\n";
			mp4ff_close(dt.infile);
			NeAACDecClose(dt.h_decoder);
			return false;
		}

/// std::cout << boost::format("Decode track: %d\n") % dt.track;

		return true;
	}

	bool aac_io::decode_mp4_param_(decode_mp4_t& dt)
	{
		unsigned char* buffer = 0;
		unsigned int buffer_size = 0;
		mp4ff_get_decoder_config(dt.infile, dt.track, &buffer, &buffer_size);

		unsigned long samplerate;
		unsigned char channels;
		if(NeAACDecInit2(dt.h_decoder, buffer, buffer_size, &samplerate, &channels) < 0) {
///	std::cout << "Error initializing decoder library.\n";
			NeAACDecClose(dt.h_decoder);
			mp4ff_close(dt.infile);
			return false;
		}

		dt.channels = channels;
		dt.samplerate = samplerate;
		dt.useAacLength = 0;
		dt.no_gapless = false;
		dt.timescale = mp4ff_time_scale(dt.infile, dt.track);
		dt.framesize = 1024;
		if(NeAACDecAudioSpecificConfig(buffer, buffer_size, &dt.mp4ASC) >= 0) {
			if(dt.mp4ASC.frameLengthFlag == 1) dt.framesize = 960;
			if(dt.mp4ASC.sbr_present_flag == 1) dt.framesize *= 2;
		}
		free(buffer);

		dt.samples = mp4ff_num_samples(dt.infile, dt.track);

		return true;
	}

	audio aac_io::decode_mp4_file_(utils::file_io& fin)
	{
		decode_mp4_t dt;
		if(!decode_track_mp4_(fin, dt)) {
			return 0;
		}

		if(!decode_mp4_param_(dt)) {
			return 0;
		}

/// list_mp4(dt.infile, dt.mp4ASC, dt.track);

		if(dt.samples <= 1) {
			return 0;
		}

		uint32_t out_size = (dt.samples - 1) * dt.framesize;
		audio aif;
		if(dt.channels == 1) {
			aif = audio(new audio_mno16);
		} else if(dt.channels == 2) {
			aif = audio(new audio_sto16);
		} else {
			std::cout << boost::format("Can't decode chanel: %d\n") % dt.channels;
			fflush(stdout);
			NeAACDecClose(dt.h_decoder);
			mp4ff_close(dt.infile);
			return aif;
		}
		aif->create(dt.samplerate, out_size);

/// std::cout << boost::format("Chanels: %d\n") % channels);
/// std::cout << boost::format("Sample rate: %d [Hz]\n") % samplerate);
/// std::cout << boost::format("Samples: %d\n") % out_size);

		dt.count = 0;
		uint32_t pos = 0;
		for(uint32_t idx = 0; idx < dt.samples; idx++) {
			dt.delay = 0;
			bool f = decode_audio_mp4_(dt, idx);
			if(!f) {
				std::cout << boost::format("Reading from MP4 file failed. (%d)\n") % dt.count;
				destroy_mp4_(dt);
				return 0;
			}

			if(dt.delay) {
/// std::cout << boost::format("Delay: %d\n") % dt.delay;
			}

			for(uint32_t i = 0; i < dt.count / dt.channels; ++i) {
				if(dt.channels == 1) {
					short* p = static_cast<short*>(dt.sample);
					pcm16_m pcm;
					pcm.w = p[i];
					aif->put(pos, pcm);
				} else if(dt.channels == 2) {
					short* p = static_cast<short*>(dt.sample);
					pcm16_s pcm;
					pcm.l = p[i * 2 + 0];
					pcm.r = p[i * 2 + 1];
					aif->put(pos, pcm);
				}
				++pos;
			}
			free(dt.tmp);
		}

		destroy_mp4_(dt);

		return aif;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	AAC ファイルか確認する
		@param[in]	fin	file_io クラス
		@return エラーなら「false」を返す
	*/
	//-----------------------------------------------------------------//
	bool aac_io::probe(utils::file_io& fin)
	{
		uint32_t pos = fin.tell();
		bool ret = false;
		uint8_t header[8];
		uint32_t len = fin.read(header, 1, 8);
		fin.seek(pos, utils::file_io::seek::set);
		if(len != 8) {
			return ret;
		}

		if(header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') {
			decode_mp4_t dt;
			if(decode_track_mp4_(fin, dt)) {
				ret = true;
				destroy_mp4_(dt);
			}
		} else {

// decode AAC...

		}
		return ret;
	}

	bool aac_io::create_mp4_info_(utils::file_io& fin, decode_mp4_t& dt, audio_info& info, info_state st)
	{
		dt.no_gapless = false;
		dt.initial = false;
		if(!decode_track_mp4_(fin, dt)) {
			return false;
		}
		if(!decode_mp4_param_(dt)) {
			return false;
		}
		if(dt.samples <= 1) {
			return false;
		}

		bool ret = true;
		if(dt.channels == 1) {
			info.type = audio_format::PCM16_MONO;
		} else if(dt.channels == 2) {
			info.type = audio_format::PCM16_STEREO;
		} else {
			ret = false;
		}
		if(ret) {
			info.samples = (dt.samples - 1) * dt.framesize;
			info.chanels = dt.channels;
			info.bits = 16;
			info.frequency = dt.samplerate;
			info.block_align = dt.channels * 2;
		}

		tag_.clear();

		int j = mp4ff_meta_get_num_items(dt.infile);
		int l = -1;
		char* art_ptr = nullptr;
		uint32_t art_size = 0;
		for(int k = 0; k < j; ++k) {
			char* item;
			char* value;
			if(mp4ff_meta_get_by_index(dt.infile, k, &item, &value)) {
				std::string s = item;
				if(s == "title") tag_.title_ = value;
				else if(s == "artist") tag_.artist_ = value;
				else if(s == "writer") tag_.writer_ = value;
				else if(s == "album") tag_.album_ = value;
				else if(s == "track") tag_.track_ = value;
				else if(s == "totaltracks") tag_.total_tracks_ = value;
				else if(s == "disc") tag_.disc_ = value;
				else if(s == "totaldiscs") tag_.total_discs_ = value;
				else if(s == "date") tag_.date_ = value;
				else if(s == "cover" && static_cast<uint8_t>(st) & static_cast<uint8_t>(info_state::apic)) {
					art_ptr = value;
					l = k;
				}
			}
			if(art_ptr != nullptr && (l + 1) == k) {
				art_size = value - art_ptr;
			}
		}
		if(art_ptr != nullptr) {
//			const uint8_t* p = (const uint8_t*)art_ptr;
//			for(int i = 0; i < 64; ++i) {
//				std::cout << boost::format("%02X") % (uint32_t)(*p);
//				if((i & 15) == 15) std::cout << std::endl;
//				else std::cout << ", ";
//				++p;
//			}
//			std::cout << std::endl;
//			uint32_t len = 65536 * 2;
//			tag_.image_ = utils::shared_array_u8(new utils::array_u8);
//			tag_.image_->copy(art_ptr, len);
		}
		tag_.update();

		return true;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	AAC ファイルの情報を取得する
		@param[in]	fin		file_io クラス
		@param[in]	info	情報を受け取る構造体
		@param[in]	st		情報ステート
		@return エラーなら「false」を返す
	*/
	//-----------------------------------------------------------------//
	bool aac_io::info(utils::file_io& fin, audio_info& info, info_state st)
	{
		long pos = fin.tell();
		uint8_t header[8];
		uint32_t len = fin.read(header, 1, 8);
		fin.seek(pos, utils::file_io::seek::set);
		if(len != 8) return false;

		if(header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') {
			decode_mp4_t dt;
			bool ret = create_mp4_info_(fin, dt, info, st);
			destroy_mp4_(dt);
			return ret;
		} else {

// info AAC

		}

		return false;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	ロードする
		@param[in]	fin	file_io クラス
		@param[in]	opt	フォーマット固有の設定文字列
		@return エラーなら「false」を返す
	*/
	//-----------------------------------------------------------------//
	bool aac_io::load(utils::file_io& fin, const std::string& opt)
	{
		long pos = fin.tell();
		uint8_t header[8];
		uint32_t len = fin.read(header, 1, 8);
		fin.seek(pos, utils::file_io::seek::set);
		if(len != 8) return false;

		if(header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') {
			audio_ = decode_mp4_file_(fin);
		} else {
			audio_ = decode_aac_file_(fin);
		}

		return (audio_ != 0);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	音楽ファイルをセーブする
		@param[in]	fout	file_io クラス
		@param[in]	opt	フォーマット固有の設定文字列
		@return エラーなら「false」を返す
	*/
	//-----------------------------------------------------------------//
	bool aac_io::save(utils::file_io& fout, const std::string& opt)
	{
		return false;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	ストリーム・オープンする
		@param[in]	fi		file_io クラス
		@param[in]	size	バッファサイズ
		@param[in]	info	オーディオ情報を受け取る
		@return 成功なら「true」
	*/
	//-----------------------------------------------------------------//
	bool aac_io::open_stream(utils::file_io& fi, int size, audio_info& info)
	{
		long pos = fi.tell();
		uint8_t header[8];
		uint32_t len = fi.read(header, 1, 8);
		fi.seek(pos, utils::file_io::seek::set);
		if(len != 8) return false;

		if(header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') {
			create_mp4_info_(fi, mp4_t_, info, info_state::all);

			if(mp4_t_.channels == 1) {
				info.type = audio_format::PCM16_MONO;
				stream_ = audio(new audio_mno16);
				buffer_ = audio(new audio_mno16);
			} else if(mp4_t_.channels == 2) {
				info.type = audio_format::PCM16_STEREO;
				stream_ = audio(new audio_sto16);
				buffer_ = audio(new audio_sto16);
			} else {
				return false;
			}
			stream_->zero();

			stream_->create(info.frequency, size);
			mp4_t_.count = 0;
			mp4_t_.delay = 0;
			index_ = 0;
			while(mp4_t_.count == 0) {
				bool f = decode_audio_mp4_(mp4_t_, index_);
				if(!f) {
					return 0;
				}
				free(mp4_t_.tmp);
				++index_;
			}
			--index_;
			buffer_->create(mp4_t_.samplerate, mp4_t_.count);
			buffer_cnt_ = 0;
			stream_cnt_ = 0;
			return true;
		} else {

// info AAC

		}

		return false;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	ストリーム・リード
		@param[in]	fin		ファイルI/O
		@param[in]	offset	開始位置
		@param[in]	samples	読み込むサンプル数
		@return 読み込んだサンプル数
	*/
	//-----------------------------------------------------------------//
	size_t aac_io::read_stream(utils::file_io& fin, size_t offset, size_t samples)
	{
		if(stream_cnt_) {
			while(stream_cnt_ < stream_->get_samples()) {
				if(mp4_t_.channels == 1) {
					pcm16_m pcm;
					buffer_->get(buffer_cnt_, pcm);
					stream_->put(stream_cnt_, pcm);
				} else {
					pcm16_s pcm;
					buffer_->get(buffer_cnt_, pcm);
					stream_->put(stream_cnt_, pcm);
				}
				++buffer_cnt_;
				++stream_cnt_;
			}
		}

		uint32_t bnum = mp4_t_.count / mp4_t_.channels;
		uint32_t idx = (offset / bnum) + index_;

		uint32_t smp = samples;

		stream_cnt_ = 0;
		for(int n = 0; n < 2; ++n) {
			mp4_t_.delay = 0;
			bool f = decode_audio_mp4_(mp4_t_, idx);
			if(!f) {
				return 0;
			}
			++idx;

			uint32_t pos = 0;
			for(uint32_t i = 0; i < bnum; ++i) {
				if(mp4_t_.channels == 1) {
					short* p = static_cast<short*>(mp4_t_.sample);
					pcm16_m pcm;
					pcm.w = p[i];
					buffer_->put(pos, pcm);
				} else if(mp4_t_.channels == 2) {
					short* p = static_cast<short*>(mp4_t_.sample);
					pcm16_s pcm;
					pcm.l = p[i * 2 + 0];
					pcm.r = p[i * 2 + 1];
					buffer_->put(pos, pcm);
				}
				++pos;
			}
			free(mp4_t_.tmp);

			for(uint32_t i = 0; i < bnum; ++i) {
				if(mp4_t_.channels == 1) {
					pcm16_m pcm;
					buffer_->get(i, pcm);
					stream_->put(stream_cnt_, pcm);
				} else {
					pcm16_s pcm;
					buffer_->get(i, pcm);
					stream_->put(stream_cnt_, pcm);
				}
				++stream_cnt_;
				--smp;
				if(smp == 0) {
					stream_cnt_ = stream_cnt_ % bnum;
					return samples;
				}
			}
		}

		if(stream_cnt_ >= stream_->get_samples()) {
			stream_cnt_ = 0;
		}

		return samples;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	ストリームをクローズ
	*/
	//-----------------------------------------------------------------//
	void aac_io::close_stream()
	{
		destroy_mp4_(mp4_t_);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	廃棄
	*/
	//-----------------------------------------------------------------//
	void aac_io::destroy()
	{
	}

}


text:
#include <duplicateConservative.h>
#include <boost/python.hpp>

using namespace boost::python;

void export_duplicateConservative()
{
  class_<DuplicateConservative, bases<Element>, boost::shared_ptr<DuplicateConservative>, boost::noncopyable>
        ("DuplicateConservative", init<std::string, int>())
    .def("class_name", &DuplicateConservative::class_name)
    .def("processing", &DuplicateConservative::processing)
    .def("flow_code",  &DuplicateConservative::flow_code)
  ;
}


text:
//  Copyright John Maddock 2008.
//  Use, modification and distribution are subject to 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)
//
#include <boost/math/policies/policy.hpp>
#include <boost/math/special_functions/math_fwd.hpp>

namespace boost{ namespace math{ namespace policies{

template <>
struct policy<
   domain_error<errno_on_error>,
   pole_error<errno_on_error>,
   overflow_error<errno_on_error>,
   evaluation_error<errno_on_error>,
   rounding_error<errno_on_error>,
   default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
{
public:
   typedef domain_error<errno_on_error> domain_error_type;
   typedef pole_error<errno_on_error> pole_error_type;
   typedef overflow_error<errno_on_error> overflow_error_type;
   typedef underflow_error<errno_on_error> underflow_error_type;
   typedef denorm_error<errno_on_error> denorm_error_type;
   typedef evaluation_error<errno_on_error> evaluation_error_type;
   typedef rounding_error<errno_on_error> rounding_error_type;
   typedef indeterminate_result_error<> indeterminate_result_error_type;
#if BOOST_MATH_DIGITS10_POLICY == 0
   typedef digits2<> precision_type;
#else
   typedef detail::precision<digits10<>, digits2<> >::type precision_type;
#endif
   typedef promote_float<> promote_float_type;
   typedef promote_double<> promote_double_type;
   typedef discrete_quantile<> discrete_quantile_type;
   typedef assert_undefined<> assert_undefined_type;
   typedef max_series_iterations<> max_series_iterations_type;
   typedef max_root_iterations<> max_root_iterations_type;
};

template <>
struct policy<
   domain_error<errno_on_error>,
   pole_error<errno_on_error>,
   overflow_error<errno_on_error>,
   evaluation_error<errno_on_error>,
   rounding_error<errno_on_error>,
   detail::forwarding_arg1,
   detail::forwarding_arg2,
   default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
{
public:
   typedef domain_error<errno_on_error> domain_error_type;
   typedef pole_error<errno_on_error> pole_error_type;
   typedef overflow_error<errno_on_error> overflow_error_type;
   typedef underflow_error<errno_on_error> underflow_error_type;
   typedef denorm_error<errno_on_error> denorm_error_type;
   typedef evaluation_error<errno_on_error> evaluation_error_type;
   typedef rounding_error<errno_on_error> rounding_error_type;
   typedef indeterminate_result_error<> indeterminate_result_error_type;
#if BOOST_MATH_DIGITS10_POLICY == 0
   typedef digits2<> precision_type;
#else
   typedef detail::precision<digits10<>, digits2<> >::type precision_type;
#endif
   typedef promote_float<false> promote_float_type;
   typedef promote_double<false> promote_double_type;
   typedef discrete_quantile<> discrete_quantile_type;
   typedef assert_undefined<> assert_undefined_type;
   typedef max_series_iterations<> max_series_iterations_type;
   typedef max_root_iterations<> max_root_iterations_type;
};

template <>
struct normalise<policy<domain_error<errno_on_error>, pole_error<errno_on_error>, overflow_error<errno_on_error>, evaluation_error<errno_on_error>, rounding_error<errno_on_error> >,
          promote_float<false>,
          promote_double<false>,
          discrete_quantile<>,
          assert_undefined<>,
          default_policy,
          default_policy,
          default_policy,
          default_policy,
          default_policy,
          default_policy,
          default_policy>
{
   typedef policy<domain_error<errno_on_error>, pole_error<errno_on_error>, overflow_error<errno_on_error>, evaluation_error<errno_on_error>, rounding_error<errno_on_error>, detail::forwarding_arg1, detail::forwarding_arg2> type;
};

template <>
struct normalise<policy<domain_error<errno_on_error>, pole_error<errno_on_error>, overflow_error<errno_on_error>, evaluation_error<errno_on_error>, rounding_error<errno_on_error>, detail::forwarding_arg1, detail::forwarding_arg2 >,
          promote_float<false>,
          promote_double<false>,
          discrete_quantile<>,
          assert_undefined<>,
          default_policy,
          default_policy,
          default_policy,
          default_policy,
          default_policy,
          default_policy,
          default_policy>
{
   typedef policy<domain_error<errno_on_error>, pole_error<errno_on_error>, overflow_error<errno_on_error>, evaluation_error<errno_on_error>, rounding_error<errno_on_error>, detail::forwarding_arg1, detail::forwarding_arg2> type;
};

}}} // namespaces

namespace c_policies{

using boost::math::policies::policy;
using boost::math::policies::errno_on_error;
using boost::math::policies::domain_error;
using boost::math::policies::pole_error;
using boost::math::policies::overflow_error;
using boost::math::policies::rounding_error;
using boost::math::policies::evaluation_error;

typedef policy<
   domain_error<errno_on_error>,
   pole_error<errno_on_error>,
   overflow_error<errno_on_error>,
   evaluation_error<errno_on_error>,
   rounding_error<errno_on_error>
> c_policy;

BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(c_policy)

}

max_stars_repo_name: zyiacas/boost-doc-zh

max_issues_repo_name: sdfict/boost-doc-zh

max_forks_repo_name: sdfict/boost-doc-zh


text:
#include <Eigen/Dense>

using namespace Eigen;
using namespace std;

typedef struct {
    MatrixXd A;
    MatrixXd B;
    VectorXd states0;
    double dt;
} ReferenceModel_Config_t;

class ReferenceModel {
protected:
    double dt;
    unsigned int nStates, nInputs, nOutputs;

    VectorXd states0;
    VectorXd states;
    MatrixXd Aref, Bref, Cref;

public:
    ReferenceModel(void);
    ~ReferenceModel(void);

    void initialize(const ReferenceModel_Config_t _config);
    void reset();
    void update(const VectorXd _inputs);
    void get_outputs(VectorXd &_outputs);
    void get_states(VectorXd &_states);
};


text:
// Copyright (c) Prevail Verifier contributors.
// SPDX-License-Identifier: MIT
#include "catch.hpp"

#include <string>
#include <variant>

#include <boost/algorithm/string/trim.hpp>

#if !defined(MAX_PATH)
#define MAX_PATH (256)
#endif

#include "asm_files.hpp"
#include "asm_ostream.hpp"
#include "asm_unmarshal.hpp"

#define TEST_OBJECT_FILE_DIRECTORY "ebpf-samples/build/"
#define TEST_ASM_FILE_DIRECTORY "ebpf-samples/asm/"
#define PRINT_CASE(file) \
    TEST_CASE("Print suite: " #file, "[print]") { \
        verify_printed_string(#file);\
    }

void verify_printed_string(const std::string& file)
{
    std::stringstream generated_output;
    auto raw_progs = read_elf(std::string(TEST_OBJECT_FILE_DIRECTORY) + file + ".o", "", nullptr, &g_ebpf_platform_linux);
    raw_program raw_prog = raw_progs.back();
    std::variant<InstructionSeq, std::string> prog_or_error = unmarshal(raw_prog);
    REQUIRE(std::holds_alternative<InstructionSeq>(prog_or_error));
    auto& program = std::get<InstructionSeq>(prog_or_error);
    print(program, generated_output, {}, true);
    std::ifstream expected_stream(std::string(TEST_ASM_FILE_DIRECTORY) + file + std::string(".asm"));
    REQUIRE(expected_stream);
    std::string expected_line;
    std::string actual_line;
    while (std::getline(expected_stream, expected_line)) {
        bool has_more = (bool)std::getline(generated_output, actual_line);
        REQUIRE(has_more);
        boost::algorithm::trim_right(expected_line);
        boost::algorithm::trim_right(actual_line);
        REQUIRE(expected_line == actual_line);
    }
    bool has_more = (bool)std::getline(expected_stream, actual_line);
    REQUIRE_FALSE(has_more);
}

PRINT_CASE(byteswap)
PRINT_CASE(ctxoffset)
PRINT_CASE(exposeptr)
PRINT_CASE(exposeptr2)
PRINT_CASE(map_in_map)
PRINT_CASE(mapoverflow)
PRINT_CASE(mapunderflow)
PRINT_CASE(mapvalue-overrun)
PRINT_CASE(nullmapref)
PRINT_CASE(packet_access)
PRINT_CASE(packet_overflow)
PRINT_CASE(packet_reallocate)
PRINT_CASE(packet_start_ok)
PRINT_CASE(stackok)
PRINT_CASE(tail_call)
PRINT_CASE(tail_call_bad)
PRINT_CASE(twomaps)
PRINT_CASE(twostackvars)
PRINT_CASE(twotypes)