<commit_before>/*
 * protocol4_serial.cpp
 *
 * PROTOCOL4 protocol over serial port
 *
 *  Created on: 2011-06-05
 *      Author: Bernard
 */

#include "extdata.h"
#include "avr_util.h"
#include "protocol4_serial.h"
#include "serial.h"
#include "console.h"
#include "strings.h"
#include "pen_event.h"
#include "wacom_usb.h"
#include <util/delay.h>

#include "led.h"

#include <stdio.h>

#define WACOM_PKGLEN_PROTOCOL4 	 	7
#define WACOM_PKGLEN_PROTOCOL4_TILT	9

#define TABLET_TYPE_UNSUPPORTED	0	// unknown/undefined protocol 4 serial tablet
#define TABLET_TYPE_ULTRAPAD	1  	// UD-*
					// Note: other tablets with Protocol 4 includes:  PL-*,ET-*,CT-*,KT-*

#define ROM_VERSION_UNSUPPORTED	0	// unknown/undefined/V1.1 or earlier
#define ROM_VERSION_1_2		2  	// lots of UD-1218-R at version 1.2
#define ROM_VERSION_1_3		3  	//
#define ROM_VERSION_1_4		4  	//
#define ROM_VERSION_1_5		5 	// tested with V1.5-4

namespace protocol4_serial
{
	enum protocol4ControllerState
	{
		initial,	//
		modelversion,	// "~#UD-1212-R V1.5-4\r"
		packet
	};

	uint8_t datalen = 0;
	uint8_t buffer[21];

	uint8_t packet_len;

	Pen::PenEvent penEvent;

	protocol4ControllerState itsCurState = packet;

	uint8_t tabletType;
	uint8_t romVersion;

	bool in_proximity;
	bool eraser_mode;

	void resetToolState()
	{
		in_proximity = false;
		eraser_mode = false;
	}

	void initialState()
	{
		// attempt to reset the board to 9600 bauds

		serial::setNormalPortSpeed(); // 19200 baud
		serial::sendString("\r\r\r\r#\r"); // send a few \r to make sure we are in sync

		// 10 ms delay
		_delay_ms(10);

		serial::setInitialPortSpeed(); // 9600 baud
		serial::sendString("\r\r\r\r#\r"); // send a few \r to make sure we are in sync

		// 10 ms delay
		_delay_ms(10);

		itsCurState = modelversion;
		serial::sendString("\r\r\r\r~#"); // send a few \r to make sure we are in sync
		datalen = 0;
	}

	bool parse_modelversion()
	{
		if(datalen != 20)
		{
			// retry !
			initialState();
			return false;
		}

		// For now, only supports this "rigid" format:
		//
		// "~#UD-1212-R00 V1.5-4" (ends with /r)

		if(buffer[2] == 'U')
		{
			tabletType = TABLET_TYPE_ULTRAPAD;
		}
		else
		{
			tabletType = TABLET_TYPE_UNSUPPORTED;
		}

		if(buffer[15] != '1')
		{
			tabletType = TABLET_TYPE_UNSUPPORTED;
		}

		if(buffer[17] == '2')
			romVersion = ROM_VERSION_1_2;
		else if(buffer[17] == '3')
			romVersion = ROM_VERSION_1_3;
		else if(buffer[17] == '4')
			romVersion = ROM_VERSION_1_4;
		else if(buffer[17] == '5')
			romVersion = ROM_VERSION_1_5;
		else
			romVersion = TABLET_TYPE_UNSUPPORTED;

		if(console::console_enabled)
		{
			console::printP(STR_SERIAL_TABLET_);
			for(uint8_t i=2;i<datalen;i++)
				console::print(buffer[i]);
			console::println();

			switch(tabletType)
			{
				case TABLET_TYPE_UNSUPPORTED:
					console::printP(STR_UNSUPPORTED);
					break;
				case TABLET_TYPE_ULTRAPAD:
					console::printP(STR_ULTRAPAD);
					break;
			}

			console::printP(STR_ROM_VERSION);

			switch(romVersion)
			{
				case ROM_VERSION_UNSUPPORTED:
					console::printP(STR_UNSUPPORTED);
					break;
				case ROM_VERSION_1_2:
					console::print("1.2");
					break;
				case ROM_VERSION_1_3:
					console::print("1.3");
					break;
				case ROM_VERSION_1_4:
					console::print("1.4");
					break;
				case ROM_VERSION_1_5:
					console::print("1.5");
					break;
			}

			console::println();
		}

		// event consumed
		datalen = 0;

		if(romVersion == ROM_VERSION_UNSUPPORTED || tabletType == TABLET_TYPE_UNSUPPORTED)
			return false;

		return true;
	}

	/**
	 * set port speed to 19200, set max resolution, set Pnp Off.
	 */
	void enableFeatures()
	{
		/*** Explanation of the bits
		 *
		 * F    2    0    3    C    8    1    0
		 * 1111 0010 0000 0011 1100 1000 0001 0000
		 *
		 * 11 WACOM-IV
		 * 11 19200 bauds  (10 - 9600 bauds)
		 * 00 None
		 * 1  8 bits
		 * 0  1 stop bit
		 *
		 * 00 no CTS/DTR check (thus may not need to ground those pins, but it is "better" not to let input pins floating anyways.)
		 * 00 suppressed
		 * 0  binary output format
		 * 0  absolute mode
		 * 11 maximum  (10 = 100pps)
		 *
		 * 11 max resolution (1270,1270) but 2540,2540 is set in the init string further down.
		 * 0  upper left origin
		 * 0  no out of range data
		 * 10 CRLF line terminator
		 * 0
		 * 0  PnP Off (1 by default)
		 *
		 * 0  firm pressure sensitivity
		 * 0  high reading height (8mm+)
		 * 0  multi-device mode disabled
		 * 1  tilt ON
		 * 0  no MM command set
		 * 0  Portrait  MM961 orientation
		 * 0  1234 - BitPad II cursor data
		 * 0  remote mode OFF
		 *
		 * 000 - increment value (IN)
		 * 00  - max pen reporting speed
		 * 2540,2540 - dpi settings
		 */
		serial::sendString("~*F203C810,000,00,2540,2540\r");

		if(romVersion >= ROM_VERSION_1_4)
			packet_len = WACOM_PKGLEN_PROTOCOL4_TILT;
		else
			packet_len = WACOM_PKGLEN_PROTOCOL4;
	}

	void onSerialByteReceived(uint8_t data)
	{
//		console::print(' ');
//		console::printHex(data, 2);
//		console::print((char)data);

		switch(itsCurState)
		{
			case initial:
			case modelversion:
				if(datalen == 0 && data != '~')
					break; // wait for first valid character

				if(datalen == 1 && data != '#')
				{
					// restart the wait
					datalen = 0;
					break;
				}

				if(data != '\r')
				{
					if(datalen < 20)
					{
						buffer[datalen] = data;
						datalen++;
					}
					else
					{
						// retry !
						initialState();
						break;
					}
				}
				else
				{
					if(parse_modelversion())
					{
						// change port speed, tilt and other thingy
						enableFeatures();

						// 10 ms delay
						_delay_ms(10);

						serial::setNormalPortSpeed(); // set serial port speed to 19200

						// test output max coords.
//						serial::sendString("\r\r~C\r");

						// read back settings.
//						serial::sendString("\r\r~R\r");

						serial::sendString("\r\rST\r");  // Start transmitting data

						itsCurState = packet;
					}
				}
				break;
			case packet:
			{
				if(data & 0x80)
				{
//					console::println();
//					console::print("*");

					if(datalen > 0)
						console::print("(?!)");
					datalen = 0;
				}
				else if(datalen == 0)
				{
					console::println("(*!)");
					return;		// wait for the first valid byte
				}

//				console::printHex(data, 2);

				if(datalen < packet_len)
				{
					buffer[datalen] = data;
					datalen++;
				}

				if(datalen == packet_len)
				{
					// event consumed
					datalen = 0;

//					console::println();

					penEvent.proximity = (buffer[0] & 0x40)?1:0;

					penEvent.x =                 buffer[2] |
							(((uint16_t) buffer[1]        ) << 7) |
							(((uint16_t)(buffer[0] & 0x3) ) << 14);

					penEvent.y =    	     buffer[5] |
							(((uint16_t) buffer[4]        ) << 7) |
							(((uint16_t)(buffer[3] & 0x3) ) << 14);

//					console::print("...x=");
//					console::printNumber(penEvent.x);
//					console::print("y=");
//					console::printNumber(penEvent.y);

					/* pressure */

					penEvent.pressure = 	(((uint16_t)(buffer[3] & 0x04)) >> 2) |
								(((uint16_t)(buffer[6] & 0x3F)) << 1);

					penEvent.pressure |= (buffer[6] & 0x40) ? 0 : 0x80;

					penEvent.is_mouse = buffer[0] & 0x20 ? 0 : 1;  // == !stylus

					/* buttons */
//					uint8_t buttons = (buffer[3] >> 3) & 0x0F;
//					console::print(" - buttons: 0x");
//					console::printHex(buttons,1);

					/* check which device (pen/eraser) is being reported */
					bool curEvent_eraser = (buffer[3] & 0x20);

					// detect tool state
					if(!in_proximity)
					{
						if(penEvent.proximity)
						{
							// entering proximity
							in_proximity = true;

							if(curEvent_eraser)
							{
								eraser_mode = true;
							}
							else
							{
								eraser_mode = false;
							}

							console::printP(STR_ENTER_PROX);
							if(eraser_mode)
								console::printlnP(STR_ERASER);
							else
								console::printlnP(STR_PEN);
							console::println();
						}
					}
					else if(!penEvent.proximity)
					{
						console::printP(STR_EXIT_PROX);
						console::println();
						resetToolState();
					}

					penEvent.eraser = eraser_mode;

					if(eraser_mode)
					{
						// no sideswitches with eraser
						penEvent.button0 = 0;
						penEvent.button1 = 0;
					}
					else
					{
						penEvent.button0 = (buffer[3] & 0x10) ? 1:0;  // sideswitch 1
						penEvent.button1 = (buffer[3] & 0x20) ? 1:0;  // sideswitch 2
					}

					// tip
					penEvent.touch = (buffer[3] & 0x08) ? 1:0; // shouldn't we look at the pressure instead?

					// TODO: understand the extra logic from the linux driver (wacserial.c)

					/* check on previous proximity */
					/* we might have been fooled by tip and second
					 * sideswitch when it came into prox */

					/* tilt mode */
					if (packet_len == WACOM_PKGLEN_PROTOCOL4_TILT)
					{
						penEvent.tilt_x = buffer[7] & 0x3F;
						penEvent.tilt_y = buffer[8] & 0x3F;
						if (buffer[7] & 0x40) penEvent.tilt_x -= 64;
						if (buffer[8] & 0x40) penEvent.tilt_y -= 64;
					}

					penEvent.rotation_z = 0;

//					console::println();

					Pen::input_pen_event(penEvent);
				}
				break;
			}
		}
	}

	void init()
	{
		console::printP(STR_PROTOCOL4_SERIAL_INIT);

		resetToolState();

		serial::init(onSerialByteReceived);

		initialState();
	}
}
<commit_msg>early support for ArtPadII<commit_after>/*
 * protocol4_serial.cpp
 *
 * PROTOCOL4 protocol over serial port
 *
 *  Created on: 2011-06-05
 *      Author: Bernard
 */

#include "extdata.h"
#include "avr_util.h"
#include "protocol4_serial.h"
#include "serial.h"
#include "console.h"
#include "strings.h"
#include "pen_event.h"
#include "wacom_usb.h"
#include <util/delay.h>

#include "led.h"

#include <stdio.h>

#define WACOM_PKGLEN_PROTOCOL4 	 	7
#define WACOM_PKGLEN_PROTOCOL4_TILT	9

#define TABLET_TYPE_UNSUPPORTED	0	// unknown/undefined protocol 4 serial tablet
#define TABLET_TYPE_ULTRAPAD	1  	// UD-*
#define TABLET_TYPE_ARTPADII    2	// KT-0405-R
#define TABLET_TYPE_PENPARTNER  3	// CT-0405-R
					// Note: other tablets with Protocol 4 includes:  PL-*,ET-*

#define ROM_VERSION_UNSUPPORTED	0	// unknown/undefined/V1.1 or earlier
#define ROM_VERSION_1_2		2  	// lots of UD-1218-R at version 1.2
#define ROM_VERSION_1_3		3  	//
#define ROM_VERSION_1_4		4  	//
#define ROM_VERSION_1_5		5 	// tested with V1.5-4

namespace protocol4_serial
{
	enum protocol4ControllerState
	{
		initial,	//
		modelversion,	// "~#UD-1212-R V1.5-4\r"
		packet
	};

	uint8_t datalen = 0;
	uint8_t buffer[21];

	uint8_t packet_len;

	Pen::PenEvent penEvent;

	protocol4ControllerState itsCurState = packet;

	uint8_t tabletType;
	uint8_t romVersion;

	bool in_proximity;
	bool eraser_mode;

	void resetToolState()
	{
		in_proximity = false;
		eraser_mode = false;
	}

	void initialState()
	{
		// attempt to reset the board to 9600 bauds

		serial::setNormalPortSpeed(); // 19200 baud
		serial::sendString("\r\r\r\r#\r"); // send a few \r to make sure we are in sync

		// 10 ms delay
		_delay_ms(10);

		serial::setInitialPortSpeed(); // 9600 baud
		serial::sendString("\r\r\r\r#\r"); // send a few \r to make sure we are in sync

		// 10 ms delay
		_delay_ms(10);

		itsCurState = modelversion;
		serial::sendString("\r\r\r\r~#"); // send a few \r to make sure we are in sync
		datalen = 0;
	}

	bool parse_modelversion()
	{
		if(datalen != 20)
		{
			// retry !
			initialState();
			return false;
		}

		// For now, only supports this "rigid" format:
		//
		// "~#UD-1212-R00 V1.5-4" (ends with /r)

		if(buffer[2] == 'U')
		{
			tabletType = TABLET_TYPE_ULTRAPAD;
		}
		else if(buffer[2] == 'K')
		{
			tabletType = TABLET_TYPE_UNSUPPORTED; // ARTPADII is with ROM 1.3
		}
		else if(buffer[2] == 'C')
		{
			tabletType = TABLET_TYPE_PENPARTNER;
		}
		else
		{
			tabletType = TABLET_TYPE_UNSUPPORTED;
		}

		if(buffer[15] != '1')
		{
			tabletType = TABLET_TYPE_UNSUPPORTED;
		}

		if(buffer[17] == '2')
			romVersion = ROM_VERSION_1_2;
		else if(buffer[17] == '3')
			romVersion = ROM_VERSION_1_3;
		else if(buffer[17] == '4')
			romVersion = ROM_VERSION_1_4;
		else if(buffer[17] == '5')
			romVersion = ROM_VERSION_1_5;
		else
			romVersion = TABLET_TYPE_UNSUPPORTED;

		if(romVersion == ROM_VERSION_1_3 && buffer[2] == 'K')
			tabletType = TABLET_TYPE_ARTPADII;

		if(console::console_enabled)
		{
			console::printP(STR_SERIAL_TABLET_);
			for(uint8_t i=2;i<datalen;i++)
				console::print(buffer[i]);
			console::println();

			switch(tabletType)
			{
				case TABLET_TYPE_UNSUPPORTED:
					console::printP(STR_UNSUPPORTED);
					break;
				case TABLET_TYPE_ULTRAPAD:
					console::printP(STR_ULTRAPAD);
					break;
				case TABLET_TYPE_ARTPADII:
					console::printP(STR_ARTPADII);
					break;
				case TABLET_TYPE_PENPARTNER:
					console::printP(STR_PENPARTNER);
					break;
			}

			console::printP(STR_ROM_VERSION);

			switch(romVersion)
			{
				case ROM_VERSION_UNSUPPORTED:
					console::printP(STR_UNSUPPORTED);
					break;
				case ROM_VERSION_1_2:
					console::print("1.2");
					break;
				case ROM_VERSION_1_3:
					console::print("1.3");
					break;
				case ROM_VERSION_1_4:
					console::print("1.4");
					break;
				case ROM_VERSION_1_5:
					console::print("1.5");
					break;
			}

			console::println();
		}

		// event consumed
		datalen = 0;

		if(romVersion == ROM_VERSION_UNSUPPORTED || tabletType == TABLET_TYPE_UNSUPPORTED)
			return false;

		return true;
	}

	/**
	 * set port speed to 19200, set max resolution, set Pnp Off.
	 */
	void enableFeatures()
	{
		/*** Explanation of the bits
		 *
		 * F    2    0    3    C    8    1    0
		 * 1111 0010 0000 0011 1100 1000 0001 0000
		 *
		 * 11 WACOM-IV
		 * 11 19200 bauds  (10 - 9600 bauds)
		 * 00 None
		 * 1  8 bits
		 * 0  1 stop bit
		 *
		 * 00 no CTS/DTR check (thus may not need to ground those pins, but it is "better" not to let input pins floating anyways.)
		 * 00 suppressed
		 * 0  binary output format
		 * 0  absolute mode
		 * 11 maximum  (10 = 100pps)
		 *
		 * 11 max resolution (1270,1270) but 2540,2540 is set in the init string further down.
		 * 0  upper left origin
		 * 0  no out of range data
		 * 10 CRLF line terminator
		 * 0
		 * 0  PnP Off (1 by default)
		 *
		 * 0  firm pressure sensitivity
		 * 0  high reading height (8mm+)
		 * 0  multi-device mode disabled
		 * 1  tilt ON
		 * 0  no MM command set
		 * 0  Portrait  MM961 orientation
		 * 0  1234 - BitPad II cursor data
		 * 0  remote mode OFF
		 *
		 * 000 - increment value (IN)
		 * 00  - max pen reporting speed
		 * 2540,2540 - dpi settings
		 */
		serial::sendString("~*F203C810,000,00,2540,2540\r");

		if(romVersion >= ROM_VERSION_1_4)
			packet_len = WACOM_PKGLEN_PROTOCOL4_TILT;
		else
			packet_len = WACOM_PKGLEN_PROTOCOL4;
	}

	void onSerialByteReceived(uint8_t data)
	{
//		console::print(' ');
//		console::printHex(data, 2);
//		console::print((char)data);

		switch(itsCurState)
		{
			case initial:
			case modelversion:
				if(datalen == 0 && data != '~')
					break; // wait for first valid character

				if(datalen == 1 && data != '#')
				{
					// restart the wait
					datalen = 0;
					break;
				}

				if(data != '\r')
				{
					if(datalen < 20)
					{
						buffer[datalen] = data;
						datalen++;
					}
					else
					{
						// retry !
						initialState();
						break;
					}
				}
				else
				{
					if(parse_modelversion())
					{
						// change port speed, tilt and other thingy
						enableFeatures();

						// 10 ms delay
						_delay_ms(10);

						serial::setNormalPortSpeed(); // set serial port speed to 19200

						// test output max coords.
//						serial::sendString("\r\r~C\r");

						// read back settings.
//						serial::sendString("\r\r~R\r");

						serial::sendString("\r\rST\r");  // Start transmitting data

						itsCurState = packet;
					}
				}
				break;
			case packet:
			{
				if(data & 0x80)
				{
//					console::println();
//					console::print("*");

					if(datalen > 0)
						console::print("(?!)");
					datalen = 0;
				}
				else if(datalen == 0)
				{
					console::println("(*!)");
					return;		// wait for the first valid byte
				}

//				console::printHex(data, 2);

				if(datalen < packet_len)
				{
					buffer[datalen] = data;
					datalen++;
				}

				if(datalen == packet_len)
				{
					// event consumed
					datalen = 0;

//					console::println();

					penEvent.proximity = (buffer[0] & 0x40)?1:0;

					penEvent.x =                 buffer[2] |
							(((uint16_t) buffer[1]        ) << 7) |
							(((uint16_t)(buffer[0] & 0x3) ) << 14);

					penEvent.y =    	     buffer[5] |
							(((uint16_t) buffer[4]        ) << 7) |
							(((uint16_t)(buffer[3] & 0x3) ) << 14);

//					console::print("...x=");
//					console::printNumber(penEvent.x);
//					console::print("y=");
//					console::printNumber(penEvent.y);

					/* pressure */

					penEvent.pressure = 	(((uint16_t)(buffer[3] & 0x04)) >> 2) |
								(((uint16_t)(buffer[6] & 0x3F)) << 1);

					penEvent.pressure |= (buffer[6] & 0x40) ? 0 : 0x80;

					penEvent.is_mouse = buffer[0] & 0x20 ? 0 : 1;  // == !stylus

					/* buttons */
//					uint8_t buttons = (buffer[3] >> 3) & 0x0F;
//					console::print(" - buttons: 0x");
//					console::printHex(buttons,1);

					/* check which device (pen/eraser) is being reported */
					bool curEvent_eraser = (buffer[3] & 0x20);

					// detect tool state
					if(!in_proximity)
					{
						if(penEvent.proximity)
						{
							// entering proximity
							in_proximity = true;

							if(curEvent_eraser)
							{
								eraser_mode = true;
							}
							else
							{
								eraser_mode = false;
							}

							console::printP(STR_ENTER_PROX);
							if(eraser_mode)
								console::printlnP(STR_ERASER);
							else
								console::printlnP(STR_PEN);
							console::println();
						}
					}
					else if(!penEvent.proximity)
					{
						console::printP(STR_EXIT_PROX);
						console::println();
						resetToolState();
					}

					penEvent.eraser = eraser_mode;

					if(eraser_mode)
					{
						// no sideswitches with eraser
						penEvent.button0 = 0;
						penEvent.button1 = 0;
					}
					else
					{
						penEvent.button0 = (buffer[3] & 0x10) ? 1:0;  // sideswitch 1
						penEvent.button1 = (buffer[3] & 0x20) ? 1:0;  // sideswitch 2
					}

					// tip
					penEvent.touch = (buffer[3] & 0x08) ? 1:0; // shouldn't we look at the pressure instead?

					// TODO: understand the extra logic from the linux driver (wacserial.c)

					/* check on previous proximity */
					/* we might have been fooled by tip and second
					 * sideswitch when it came into prox */

					/* tilt mode */
					if (packet_len == WACOM_PKGLEN_PROTOCOL4_TILT)
					{
						penEvent.tilt_x = buffer[7] & 0x3F;
						penEvent.tilt_y = buffer[8] & 0x3F;
						if (buffer[7] & 0x40) penEvent.tilt_x -= 64;
						if (buffer[8] & 0x40) penEvent.tilt_y -= 64;
					}

					penEvent.rotation_z = 0;

//					console::println();

					Pen::input_pen_event(penEvent);
				}
				break;
			}
		}
	}

	void init()
	{
		console::printP(STR_PROTOCOL4_SERIAL_INIT);

		resetToolState();

		serial::init(onSerialByteReceived);

		initialState();
	}
}
<|endoftext|>


<commit_before>#define DMLC_ENABLE_STD_THREAD 0

#pragma GCC optimize ( "-Os" )

#include "../xgboost/src/c_api/c_api.cc"
#include "../xgboost/src/data/simple_csr_source.cc"
#include "../xgboost/dmlc-core/src/data.cc"
#include "../xgboost/src/data/data.cc"
#include "../xgboost/src/logging.cc"
#include "../xgboost/rabit/src/c_api.cc"
#include "../xgboost/rabit/src/engine.cc"
#include "../xgboost/rabit/src/allreduce_base.cc"
#include "../xgboost/rabit/src/allreduce_robust.cc"
#include "../xgboost/src/c_api/c_api_error.cc"
#include "../xgboost/dmlc-core/src/io.cc"
#include "../xgboost/dmlc-core/src/io/local_filesys.cc"
#include "../xgboost/src/learner.cc"
#include "../xgboost/src/objective/objective.cc"
#include "../xgboost/dmlc-core/src/io/input_split_base.cc"
#include "../xgboost/src/common/common.cc"
#include "../xgboost/src/gbm/gbm.cc"
#include "../xgboost/dmlc-core/src/io/recordio_split.cc"
#include "../xgboost/src/metric/metric.cc"
#include "../xgboost/src/data/simple_dmatrix.cc"
#include "../xgboost/dmlc-core/src/io/line_split.cc"
#include "../xgboost/src/objective/regression_obj.cc"
#include "../xgboost/src/objective/multiclass_obj.cc"
#include "../xgboost/src/metric/elementwise_metric.cc"
#include "../xgboost/src/metric/multiclass_metric.cc"
#include "../xgboost/src/metric/rank_metric.cc"
#include "../xgboost/src/gbm/gbtree.cc"
#include "../xgboost/src/gbm/gblinear.cc"
#include "../xgboost/src/data/sparse_page_raw_format.cc"
#include "../xgboost/src/objective/rank_obj.cc"
#include "../xgboost/src/tree/tree_updater.cc"
#include "../xgboost/src/tree/updater_histmaker.cc"
#include "../xgboost/src/tree/updater_colmaker.cc"
#include "../xgboost/src/tree/updater_skmaker.cc"
#include "../xgboost/src/tree/updater_prune.cc"
#include "../xgboost/src/tree/updater_refresh.cc"
#include "../xgboost/src/tree/updater_sync.cc"
#include "../xgboost/src/tree/tree_model.cc"

#include "MMRF.hpp"
<commit_msg>#pragma GCC optimize ( "-O2" )<commit_after>#define DMLC_ENABLE_STD_THREAD 0

#pragma GCC optimize ( "-O2" )

#include "../xgboost/src/c_api/c_api.cc"
#include "../xgboost/src/data/simple_csr_source.cc"
#include "../xgboost/dmlc-core/src/data.cc"
#include "../xgboost/src/data/data.cc"
#include "../xgboost/src/logging.cc"
#include "../xgboost/rabit/src/c_api.cc"
#include "../xgboost/rabit/src/engine.cc"
#include "../xgboost/rabit/src/allreduce_base.cc"
#include "../xgboost/rabit/src/allreduce_robust.cc"
#include "../xgboost/src/c_api/c_api_error.cc"
#include "../xgboost/dmlc-core/src/io.cc"
#include "../xgboost/dmlc-core/src/io/local_filesys.cc"
#include "../xgboost/src/learner.cc"
#include "../xgboost/src/objective/objective.cc"
#include "../xgboost/dmlc-core/src/io/input_split_base.cc"
#include "../xgboost/src/common/common.cc"
#include "../xgboost/src/gbm/gbm.cc"
#include "../xgboost/dmlc-core/src/io/recordio_split.cc"
#include "../xgboost/src/metric/metric.cc"
#include "../xgboost/src/data/simple_dmatrix.cc"
#include "../xgboost/dmlc-core/src/io/line_split.cc"
#include "../xgboost/src/objective/regression_obj.cc"
#include "../xgboost/src/objective/multiclass_obj.cc"
#include "../xgboost/src/metric/elementwise_metric.cc"
#include "../xgboost/src/metric/multiclass_metric.cc"
#include "../xgboost/src/metric/rank_metric.cc"
#include "../xgboost/src/gbm/gbtree.cc"
#include "../xgboost/src/gbm/gblinear.cc"
#include "../xgboost/src/data/sparse_page_raw_format.cc"
#include "../xgboost/src/objective/rank_obj.cc"
#include "../xgboost/src/tree/tree_updater.cc"
#include "../xgboost/src/tree/updater_histmaker.cc"
#include "../xgboost/src/tree/updater_colmaker.cc"
#include "../xgboost/src/tree/updater_skmaker.cc"
#include "../xgboost/src/tree/updater_prune.cc"
#include "../xgboost/src/tree/updater_refresh.cc"
#include "../xgboost/src/tree/updater_sync.cc"
#include "../xgboost/src/tree/tree_model.cc"

#include "MMRF.hpp"
<|endoftext|>


<commit_before>/**
 * @file streaming_decision_tree.hpp
 * @author Ryan Curtin
 *
 * The core class for a streaming decision tree.
 */
#ifndef __MLPACK_METHODS_HOEFFDING_TREES_STREAMING_DECISION_TREE_HPP
#define __MLPACK_METHODS_HOEFFDING_TREES_STREAMING_DECISION_TREE_HPP

#include <mlpack/core.hpp>

namespace mlpack {
namespace tree {

template<
  typename SplitType,
  typename MatType = arma::mat
>
class StreamingDecisionTree
{
 public:
  StreamingDecisionTree(const MatType& data,
                        const data::DatasetInfo& datasetInfo,
                        const arma::Row<size_t>& labels,
                        const size_t numClasses,
                        const double confidence = 0.95,
                        const size_t numSamples = 5000);

  StreamingDecisionTree(const data::DatasetInfo& datasetInfo,
                        const size_t dimensionality,
                        const size_t numClasses,
                        const double confidence = 0.95,
                        const size_t numSamples = 5000,
                        std::unordered_map<size_t, std::pair<size_t, size_t>>*
                            dimensionMappings = NULL);

  StreamingDecisionTree(const StreamingDecisionTree& other);

  size_t NumChildren() const { return children.size(); }
  StreamingDecisionTree& Child(const size_t i) { return children[i]; }
  const StreamingDecisionTree& Child(const size_t i) const { return children[i];
}

  const SplitType& Split() const { return split; }

  template<typename VecType>
  void Train(const VecType& data, const size_t label);

  void Train(const MatType& data, const arma::Row<size_t>& labels);

  template<typename VecType>
  size_t Classify(const VecType& data);

  void Classify(const MatType& data, arma::Row<size_t>& predictions);

  size_t& MajorityClass() { return split.MajorityClass(); }

  // How do we encode the actual split itself?

  // that's just a split dimension and a rule (categorical or numeric)

 private:
  std::vector<StreamingDecisionTree> children;

  SplitType split;
};

} // namespace tree
} // namespace mlpack

// Include implementation.
#include "streaming_decision_tree_impl.hpp"

#endif
<commit_msg>Add Serialize().<commit_after>/**
 * @file streaming_decision_tree.hpp
 * @author Ryan Curtin
 *
 * The core class for a streaming decision tree.
 */
#ifndef __MLPACK_METHODS_HOEFFDING_TREES_STREAMING_DECISION_TREE_HPP
#define __MLPACK_METHODS_HOEFFDING_TREES_STREAMING_DECISION_TREE_HPP

#include <mlpack/core.hpp>

namespace mlpack {
namespace tree {

template<
  typename SplitType,
  typename MatType = arma::mat
>
class StreamingDecisionTree
{
 public:
  StreamingDecisionTree(const MatType& data,
                        const data::DatasetInfo& datasetInfo,
                        const arma::Row<size_t>& labels,
                        const size_t numClasses,
                        const double confidence = 0.95,
                        const size_t numSamples = 5000);

  StreamingDecisionTree(const data::DatasetInfo& datasetInfo,
                        const size_t dimensionality,
                        const size_t numClasses,
                        const double confidence = 0.95,
                        const size_t numSamples = 5000,
                        std::unordered_map<size_t, std::pair<size_t, size_t>>*
                            dimensionMappings = NULL);

  StreamingDecisionTree(const StreamingDecisionTree& other);

  size_t NumChildren() const { return children.size(); }
  StreamingDecisionTree& Child(const size_t i) { return children[i]; }
  const StreamingDecisionTree& Child(const size_t i) const { return children[i];
}

  const SplitType& Split() const { return split; }

  template<typename VecType>
  void Train(const VecType& data, const size_t label);

  void Train(const MatType& data, const arma::Row<size_t>& labels);

  template<typename VecType>
  size_t Classify(const VecType& data);

  void Classify(const MatType& data, arma::Row<size_t>& predictions);

  size_t& MajorityClass() { return split.MajorityClass(); }

  // How do we encode the actual split itself?

  // that's just a split dimension and a rule (categorical or numeric)

  template<typename Archive>
  void Serialize(Archive& ar, const unsigned int /* version */)
  {
    ar & data::CreateNVP(split, "split");

    //ar & data::CreateNVP(children, "children");
  }

 private:
  std::vector<StreamingDecisionTree> children;

  SplitType split;
};

} // namespace tree
} // namespace mlpack

// Include implementation.
#include "streaming_decision_tree_impl.hpp"

#endif
<|endoftext|>


<commit_before>#include <ctime>
#include <iostream>
#include <cassert>
#include <fcntl.h>
#include <map>

#include "policy/kasp.pb.h"
#include "zone/zonelist.pb.h"
#include "keystate/keystate.pb.h"
#include "hsmkey/hsmkey.pb.h"

#include "enforcer/enforcerdata.h"
#include "enforcer/enforcer.h"

// Interface of this cpp file is used by C code, we need to declare
// extern "C" to prevent linking errors.
extern "C" {
#include "enforcer/enforce_task.h"
#include "shared/duration.h"
#include "shared/file.h"
}

#include "enforcer/enforcerzone.h"
#include "enforcer/hsmkeyfactory.h"

static const char *enforce_task_str = "enforce_task";

time_t perform_enforce(int sockfd, engineconfig_type *config)
{
    char buf[ODS_SE_MAXLINE];
    const char *datastore = config->datastore;
    int fd;

	GOOGLE_PROTOBUF_VERIFY_VERSION;

    // Read the zonelist and policies in from the same directory as
    // the database, use serialized protocolbuffer for now, but switch
    // to using database table ASAP.

    bool bFailedToLoad = false;

    ::ods::kasp::KaspDocument *kaspDoc = new ::ods::kasp::KaspDocument;
    {
        std::string datapath(datastore);
        datapath += ".policy.pb";
        int fd = open(datapath.c_str(),O_RDONLY);
        if (kaspDoc->ParseFromFileDescriptor(fd)) {
            ods_log_debug("[%s] policies have been loaded",
                          enforce_task_str);
        } else {
            ods_log_error("[%s] policies could not be loaded from \"%s\"",
                          enforce_task_str,datapath.c_str());
            bFailedToLoad = true;
        }
        close(fd);
    }

    ::ods::keystate::KeyStateDocument *keystateDoc =
    new ::ods::keystate::KeyStateDocument;
    {
        std::string datapath(datastore);
        datapath += ".keystate.pb";
        int fd = open(datapath.c_str(),O_RDONLY);
        if (keystateDoc->ParseFromFileDescriptor(fd)) {
            ods_log_debug("[%s] keystates have been loaded",
                          enforce_task_str);
        } else {
            ods_log_error("[%s] keystates could not be loaded from \"%s\"",
                          enforce_task_str,datapath.c_str());
        }
        close(fd);
    }

    ::ods::hsmkey::HsmKeyDocument *hsmkeyDoc =
        new ::ods::hsmkey::HsmKeyDocument;
    {
        std::string datapath(datastore);
        datapath += ".hsmkey.pb";
        int fd = open(datapath.c_str(),O_RDONLY);
        if (hsmkeyDoc->ParseFromFileDescriptor(fd)) {
            ods_log_debug("[%s] HSM key info list has been loaded",
                          enforce_task_str);
        } else {
            ods_log_error("[%s] HSM key info list could not be loaded from \"%s\"",
                          enforce_task_str,datapath.c_str());
        }
        close(fd);
    }

    if (bFailedToLoad) {
        delete kaspDoc;
        delete keystateDoc;
        delete hsmkeyDoc;
        ods_log_error("[%s] unable to continue",
                      enforce_task_str);
        return -1;
    }

    time_t t_when = time_now() + 1 * 365 * 24 * 60 * 60; // now + 1 year

    // Hook the key factory into the hsmkeyDoc list of pre-generated
    // cryptographic keys.
    HsmKeyFactoryPB keyfactory(hsmkeyDoc);

    // Go through all the zones and run the enforcer for every one of them.
    for (int z=0; z<keystateDoc->zones_size(); ++z) {

        const ::ods::keystate::EnforcerZone &ks_zone = keystateDoc->zones(z);

        const ::ods::kasp::KASP &kasp = kaspDoc->kasp();

        //printf("%s\n",zone.name().c_str());

        const ::ods::kasp::Policy *policy = NULL;

        for (int p=0; p<kasp.policies_size(); ++p) {
            // lookup the policy associated with this zone
            // printf("%s\n",kasp.policies(p).name().c_str());
            if (kasp.policies(p).name() == ks_zone.policy()) {
                policy = &kasp.policies(p);
                ods_log_debug("[%s] policy %s found for zone %s",
                              enforce_task_str,policy->name().c_str(),
                              ks_zone.name().c_str());
                break;
            }
        }

        if (policy == NULL) {
            ods_log_error("[%s] policy %s could not be found for zone %s",
                          enforce_task_str,ks_zone.policy().c_str(),
                          ks_zone.name().c_str());
            ods_log_error("[%s] unable to enforce zone %s",
                          enforce_task_str,ks_zone.name().c_str());
            continue;
        }

        EnforcerZonePB enfZone(keystateDoc->mutable_zones(z), policy);

        time_t t_next = update(enfZone, time_now(), keyfactory);

        if (t_next == -1)
            continue;

        if (t_next < time_now()) {
            ods_log_error("[%s] enforcer asked to be scheduled in the past for "
                          "zone %s", enforce_task_str, ks_zone.name().c_str());
            continue;
        }

        // If this enforcer wants a reschedule earlier than currently
        // set, then use that.
        if (t_next < t_when) {
            t_when = t_next;
            std::cout << std::endl << "Next update scheduled at " <<
            ctime(&t_when) << std::endl;
        }
    }

    // Persist the keystate zones back to disk as they may have
    // been changed by the enforcer update
    if (keystateDoc->IsInitialized()) {
        std::string datapath(datastore);
        datapath += ".keystate.pb";
        int fd = open(datapath.c_str(),O_WRONLY|O_CREAT, 0644);
        if (keystateDoc->SerializeToFileDescriptor(fd)) {
            ods_log_debug("[%s] key states have been updated",
                          enforce_task_str);

            (void)snprintf(buf, ODS_SE_MAXLINE, "update of key states completed.\n");
            ods_writen(sockfd, buf, strlen(buf));
        } else {
            (void)snprintf(buf, ODS_SE_MAXLINE, "error: key states file could not be written.\n");
            ods_writen(sockfd, buf, strlen(buf));
        }
        close(fd);
    } else {
        (void)snprintf(buf, ODS_SE_MAXLINE, "error: a message in the key states is missing mandatory information.\n");
        ods_writen(sockfd, buf, strlen(buf));
    }

    // Persist the hsmkey doc back to disk as it may have
    // been changed by the enforcer update
    if (hsmkeyDoc->IsInitialized()) {
        std::string datapath(datastore);
        datapath += ".hsmkey.pb";
        int fd = open(datapath.c_str(),O_WRONLY|O_CREAT, 0644);
        if (hsmkeyDoc->SerializeToFileDescriptor(fd)) {
            ods_log_debug("[%s] HSM keys have been updated",
                          enforce_task_str);

            (void)snprintf(buf, ODS_SE_MAXLINE, "update of HSM keys completed.\n");
            ods_writen(sockfd, buf, strlen(buf));
        } else {
            (void)snprintf(buf, ODS_SE_MAXLINE, "error: HSM keys file could not be written.\n");
            ods_writen(sockfd, buf, strlen(buf));
        }
        close(fd);
    } else {
        (void)snprintf(buf, ODS_SE_MAXLINE, "error: a message in the HSM keys is missing mandatory information.\n");
        ods_writen(sockfd, buf, strlen(buf));
    }

    delete kaspDoc;
    delete keystateDoc;
    delete hsmkeyDoc;

    return t_when;
}

static task_type *
enforce_task_perform(task_type *task)
{
    time_t t_when = perform_enforce(-1, (engineconfig_type *)task->context);

    if (t_when == -1) {
        task_cleanup(task);
        return NULL;
    }

	task->backoff = 0;
    task->when = time_now() + 60;
    return task;
}

task_type *
enforce_task(engineconfig_type *config)
{
    task_id what = task_register("enforce",
                                 "enforce_task_perform",
                                 enforce_task_perform);
	return task_create(what, time_now(), "all", (void*)config);
}
<commit_msg>Layout cleanups<commit_after>#include <ctime>
#include <iostream>
#include <cassert>
#include <fcntl.h>
#include <map>

#include "policy/kasp.pb.h"
#include "zone/zonelist.pb.h"
#include "keystate/keystate.pb.h"
#include "hsmkey/hsmkey.pb.h"

#include "enforcer/enforcerdata.h"
#include "enforcer/enforcer.h"

// Interface of this cpp file is used by C code, we need to declare
// extern "C" to prevent linking errors.
extern "C" {
#include "enforcer/enforce_task.h"
#include "shared/duration.h"
#include "shared/file.h"
}

#include "enforcer/enforcerzone.h"
#include "enforcer/hsmkeyfactory.h"

static const char *module_str = "enforce_task";

time_t perform_enforce(int sockfd, engineconfig_type *config)
{
    char buf[ODS_SE_MAXLINE];
    const char *datastore = config->datastore;
    int fd;

	GOOGLE_PROTOBUF_VERIFY_VERSION;

    // Read the zonelist and policies in from the same directory as
    // the database, use serialized protocolbuffer for now, but switch
    // to using database table ASAP.

    bool bFailedToLoad = false;

    ::ods::kasp::KaspDocument *kaspDoc = new ::ods::kasp::KaspDocument;
    {
        std::string datapath(datastore);
        datapath += ".policy.pb";
        int fd = open(datapath.c_str(),O_RDONLY);
        if (kaspDoc->ParseFromFileDescriptor(fd)) {
            ods_log_debug("[%s] policies have been loaded",
                          module_str);
        } else {
            ods_log_error("[%s] policies could not be loaded from \"%s\"",
                          module_str,datapath.c_str());
            bFailedToLoad = true;
        }
        close(fd);
    }

    ::ods::keystate::KeyStateDocument *keystateDoc =
    new ::ods::keystate::KeyStateDocument;
    {
        std::string datapath(datastore);
        datapath += ".keystate.pb";
        int fd = open(datapath.c_str(),O_RDONLY);
        if (keystateDoc->ParseFromFileDescriptor(fd)) {
            ods_log_debug("[%s] keystates have been loaded",
                          module_str);
        } else {
            ods_log_error("[%s] keystates could not be loaded from \"%s\"",
                          module_str,datapath.c_str());
        }
        close(fd);
    }

    ::ods::hsmkey::HsmKeyDocument *hsmkeyDoc =
        new ::ods::hsmkey::HsmKeyDocument;
    {
        std::string datapath(datastore);
        datapath += ".hsmkey.pb";
        int fd = open(datapath.c_str(),O_RDONLY);
        if (hsmkeyDoc->ParseFromFileDescriptor(fd)) {
            ods_log_debug("[%s] HSM key list has been loaded",
                          module_str);
        } else {
            ods_log_error("[%s] HSM key list could not be loaded from \"%s\"",
                          module_str,datapath.c_str());
        }
        close(fd);
    }

    if (bFailedToLoad) {
        delete kaspDoc;
        delete keystateDoc;
        delete hsmkeyDoc;
        ods_log_error("[%s] unable to continue",
                      module_str);
        return -1;
    }

    time_t t_when = time_now() + 1 * 365 * 24 * 60 * 60; // now + 1 year

    // Hook the key factory into the hsmkeyDoc list of pre-generated
    // cryptographic keys.
    HsmKeyFactoryPB keyfactory(hsmkeyDoc);

    // Go through all the zones and run the enforcer for every one of them.
    for (int z=0; z<keystateDoc->zones_size(); ++z) {

        const ::ods::keystate::EnforcerZone &ks_zone = keystateDoc->zones(z);

        const ::ods::kasp::KASP &kasp = kaspDoc->kasp();

        //printf("%s\n",zone.name().c_str());

        const ::ods::kasp::Policy *policy = NULL;

        for (int p=0; p<kasp.policies_size(); ++p) {
            // lookup the policy associated with this zone
            // printf("%s\n",kasp.policies(p).name().c_str());
            if (kasp.policies(p).name() == ks_zone.policy()) {
                policy = &kasp.policies(p);
                ods_log_debug("[%s] policy %s found for zone %s",
                              module_str,policy->name().c_str(),
                              ks_zone.name().c_str());
                break;
            }
        }

        if (policy == NULL) {
            ods_log_error("[%s] policy %s could not be found for zone %s",
                          module_str,ks_zone.policy().c_str(),
                          ks_zone.name().c_str());
            ods_log_error("[%s] unable to enforce zone %s",
                          module_str,ks_zone.name().c_str());
            continue;
        }

        EnforcerZonePB enfZone(keystateDoc->mutable_zones(z), policy);

        time_t t_next = update(enfZone, time_now(), keyfactory);

        if (t_next == -1)
            continue;

        if (t_next < time_now()) {
            ods_log_error("[%s] enforcer asked to be scheduled in the past for "
                          "zone %s", module_str, ks_zone.name().c_str());
            continue;
        }

        // If this enforcer wants a reschedule earlier than currently
        // set, then use that.
        if (t_next < t_when) {
            t_when = t_next;
            std::cout << std::endl << "Next update scheduled at " <<
            ctime(&t_when) << std::endl;
        }
    }

    // Persist the keystate zones back to disk as they may have
    // been changed by the enforcer update
    if (keystateDoc->IsInitialized()) {
        std::string datapath(datastore);
        datapath += ".keystate.pb";
        int fd = open(datapath.c_str(),O_WRONLY|O_CREAT, 0644);
        if (keystateDoc->SerializeToFileDescriptor(fd)) {
            ods_log_debug("[%s] key states have been updated",
                          module_str);

            (void)snprintf(buf, ODS_SE_MAXLINE,
                           "update of key states completed.\n");
            ods_writen(sockfd, buf, strlen(buf));
        } else {
            (void)snprintf(buf, ODS_SE_MAXLINE,
                           "error: key states file could not be written.\n");
            ods_writen(sockfd, buf, strlen(buf));
        }
        close(fd);
    } else {
        (void)snprintf(buf, ODS_SE_MAXLINE,
                       "error: a message in the key states is missing "
                       "mandatory information.\n");
        ods_writen(sockfd, buf, strlen(buf));
    }

    // Persist the hsmkey doc back to disk as it may have
    // been changed by the enforcer update
    if (hsmkeyDoc->IsInitialized()) {
        std::string datapath(datastore);
        datapath += ".hsmkey.pb";
        int fd = open(datapath.c_str(),O_WRONLY|O_CREAT, 0644);
        if (hsmkeyDoc->SerializeToFileDescriptor(fd)) {
            ods_log_debug("[%s] HSM keys have been updated",
                          module_str);

            (void)snprintf(buf, ODS_SE_MAXLINE,
                           "update of HSM keys completed.\n");
            ods_writen(sockfd, buf, strlen(buf));
        } else {
            (void)snprintf(buf, ODS_SE_MAXLINE,
                           "error: HSM keys file could not be written.\n");
            ods_writen(sockfd, buf, strlen(buf));
        }
        close(fd);
    } else {
        (void)snprintf(buf, ODS_SE_MAXLINE,
                       "error: a message in the HSM keys is missing "
                       "mandatory information.\n");
        ods_writen(sockfd, buf, strlen(buf));
    }

    delete kaspDoc;
    delete keystateDoc;
    delete hsmkeyDoc;

    return t_when;
}

static task_type *
enforce_task_perform(task_type *task)
{
    time_t t_when = perform_enforce(-1, (engineconfig_type *)task->context);

    if (t_when == -1) {
        task_cleanup(task);
        return NULL;
    }

	task->backoff = 0;
    task->when = time_now() + 60;
    return task;
}

task_type *
enforce_task(engineconfig_type *config)
{
    task_id what = task_register("enforce",
                                 "enforce_task_perform",
                                 enforce_task_perform);
	return task_create(what, time_now(), "all", (void*)config);
}
<|endoftext|>


<commit_before>//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "LibCxx.h"

#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

namespace {

class ListEntry {
public:
  ListEntry() = default;
  ListEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
  ListEntry(const ListEntry &rhs) = default;
  ListEntry(ValueObject *entry)
      : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}

  ListEntry next() {
    static ConstString g_next("__next_");

    if (!m_entry_sp)
      return ListEntry();
    return ListEntry(m_entry_sp->GetChildMemberWithName(g_next, true));
  }

  ListEntry prev() {
    static ConstString g_prev("__prev_");

    if (!m_entry_sp)
      return ListEntry();
    return ListEntry(m_entry_sp->GetChildMemberWithName(g_prev, true));
  }

  uint64_t value() const {
    if (!m_entry_sp)
      return 0;
    return m_entry_sp->GetValueAsUnsigned(0);
  }

  bool null() { return (value() == 0); }

  explicit operator bool() { return GetEntry() && !null(); }

  ValueObjectSP GetEntry() { return m_entry_sp; }

  void SetEntry(ValueObjectSP entry) { m_entry_sp = entry; }

  bool operator==(const ListEntry &rhs) const { return value() == rhs.value(); }

  bool operator!=(const ListEntry &rhs) const { return !(*this == rhs); }

private:
  ValueObjectSP m_entry_sp;
};

class ListIterator {
public:
  ListIterator() = default;
  ListIterator(ListEntry entry) : m_entry(entry) {}
  ListIterator(ValueObjectSP entry) : m_entry(entry) {}
  ListIterator(const ListIterator &rhs) = default;
  ListIterator(ValueObject *entry) : m_entry(entry) {}

  ValueObjectSP value() { return m_entry.GetEntry(); }

  ValueObjectSP advance(size_t count) {
    if (count == 0)
      return m_entry.GetEntry();
    if (count == 1) {
      next();
      return m_entry.GetEntry();
    }
    while (count > 0) {
      next();
      count--;
      if (m_entry.null())
        return lldb::ValueObjectSP();
    }
    return m_entry.GetEntry();
  }

  bool operator==(const ListIterator &rhs) const {
    return (rhs.m_entry == m_entry);
  }

protected:
  void next() { m_entry = m_entry.next(); }

  void prev() { m_entry = m_entry.prev(); }

private:
  ListEntry m_entry;
};

class AbstractListFrontEnd : public SyntheticChildrenFrontEnd {
public:
  size_t GetIndexOfChildWithName(ConstString name) override {
    return ExtractIndexFromString(name.GetCString());
  }
  bool MightHaveChildren() override { return true; }
  bool Update() override;

protected:
  AbstractListFrontEnd(ValueObject &valobj)
      : SyntheticChildrenFrontEnd(valobj) {}

  size_t m_count;
  ValueObject *m_head;

  static constexpr bool g_use_loop_detect = true;
  size_t m_loop_detected; // The number of elements that have had loop detection
                          // run over them.
  ListEntry m_slow_runner; // Used for loop detection
  ListEntry m_fast_runner; // Used for loop detection

  size_t m_list_capping_size;
  CompilerType m_element_type;
  std::map<size_t, ListIterator> m_iterators;

  bool HasLoop(size_t count);
  ValueObjectSP GetItem(size_t idx);
};

class ForwardListFrontEnd : public AbstractListFrontEnd {
public:
  ForwardListFrontEnd(ValueObject &valobj);

  size_t CalculateNumChildren() override;
  ValueObjectSP GetChildAtIndex(size_t idx) override;
  bool Update() override;
};

class ListFrontEnd : public AbstractListFrontEnd {
public:
  ListFrontEnd(lldb::ValueObjectSP valobj_sp);

  ~ListFrontEnd() override = default;

  size_t CalculateNumChildren() override;

  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

  bool Update() override;

private:
  lldb::addr_t m_node_address;
  ValueObject *m_tail;
};

} // end anonymous namespace

bool AbstractListFrontEnd::Update() {
  m_loop_detected = 0;
  m_count = UINT32_MAX;
  m_head = nullptr;
  m_list_capping_size = 0;
  m_slow_runner.SetEntry(nullptr);
  m_fast_runner.SetEntry(nullptr);
  m_iterators.clear();

  if (m_backend.GetTargetSP())
    m_list_capping_size =
        m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
  if (m_list_capping_size == 0)
    m_list_capping_size = 255;

  CompilerType list_type = m_backend.GetCompilerType();
  if (list_type.IsReferenceType())
    list_type = list_type.GetNonReferenceType();

  if (list_type.GetNumTemplateArguments() == 0)
    return false;
  m_element_type = list_type.GetTypeTemplateArgument(0);

  return false;
}

bool AbstractListFrontEnd::HasLoop(size_t count) {
  if (!g_use_loop_detect)
    return false;
  // don't bother checking for a loop if we won't actually need to jump nodes
  if (m_count < 2)
    return false;

  if (m_loop_detected == 0) {
    // This is the first time we are being run (after the last update). Set up
    // the loop invariant for the first element.
    m_slow_runner = ListEntry(m_head).next();
    m_fast_runner = m_slow_runner.next();
    m_loop_detected = 1;
  }

  // Loop invariant:
  // Loop detection has been run over the first m_loop_detected elements. If
  // m_slow_runner == m_fast_runner then the loop has been detected after
  // m_loop_detected elements.
  const size_t steps_to_run = std::min(count, m_count);
  while (m_loop_detected < steps_to_run && m_slow_runner && m_fast_runner &&
         m_slow_runner != m_fast_runner) {

    m_slow_runner = m_slow_runner.next();
    m_fast_runner = m_fast_runner.next().next();
    m_loop_detected++;
  }
  if (count <= m_loop_detected)
    return false; // No loop in the first m_loop_detected elements.
  if (!m_slow_runner || !m_fast_runner)
    return false; // Reached the end of the list. Definitely no loops.
  return m_slow_runner == m_fast_runner;
}

ValueObjectSP AbstractListFrontEnd::GetItem(size_t idx) {
  size_t advance = idx;
  ListIterator current(m_head);
  if (idx > 0) {
    auto cached_iterator = m_iterators.find(idx - 1);
    if (cached_iterator != m_iterators.end()) {
      current = cached_iterator->second;
      advance = 1;
    }
  }
  ValueObjectSP value_sp = current.advance(advance);
  m_iterators[idx] = current;
  return value_sp;
}

ForwardListFrontEnd::ForwardListFrontEnd(ValueObject &valobj)
    : AbstractListFrontEnd(valobj) {
  Update();
}

size_t ForwardListFrontEnd::CalculateNumChildren() {
  if (m_count != UINT32_MAX)
    return m_count;

  ListEntry current(m_head);
  m_count = 0;
  while (current && m_count < m_list_capping_size) {
    ++m_count;
    current = current.next();
  }
  return m_count;
}

ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) {
  if (idx >= CalculateNumChildren())
    return nullptr;

  if (!m_head)
    return nullptr;

  if (HasLoop(idx + 1))
    return nullptr;

  ValueObjectSP current_sp = GetItem(idx);
  if (!current_sp)
    return nullptr;

  current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
  if (!current_sp)
    return nullptr;

  // we need to copy current_sp into a new object otherwise we will end up with
  // all items named __value_
  DataExtractor data;
  Status error;
  current_sp->GetData(data, error);
  if (error.Fail())
    return nullptr;

  return CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data,
                                   m_backend.GetExecutionContextRef(),
                                   m_element_type);
}

static ValueObjectSP GetValueOfCompressedPair(ValueObject &pair) {
  ValueObjectSP value = pair.GetChildMemberWithName(ConstString("__value_"), true);
  if (! value) {
    // pre-r300140 member name
    value = pair.GetChildMemberWithName(ConstString("__first_"), true);
  }
  return value;
}

bool ForwardListFrontEnd::Update() {
  AbstractListFrontEnd::Update();

  Status err;
  ValueObjectSP backend_addr(m_backend.AddressOf(err));
  if (err.Fail() || !backend_addr)
    return false;

  ValueObjectSP impl_sp(
      m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true));
  if (!impl_sp)
    return false;
  impl_sp = GetValueOfCompressedPair(*impl_sp);
  if (!impl_sp)
    return false;
  m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
  return false;
}

ListFrontEnd::ListFrontEnd(lldb::ValueObjectSP valobj_sp)
    : AbstractListFrontEnd(*valobj_sp), m_node_address(), m_tail(nullptr) {
  if (valobj_sp)
    Update();
}

size_t ListFrontEnd::CalculateNumChildren() {
  if (m_count != UINT32_MAX)
    return m_count;
  if (!m_head || !m_tail || m_node_address == 0)
    return 0;
  ValueObjectSP size_alloc(
      m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
  if (size_alloc) {
    ValueObjectSP value = GetValueOfCompressedPair(*size_alloc);
    if (value) {
      m_count = value->GetValueAsUnsigned(UINT32_MAX);
    }
  }
  if (m_count != UINT32_MAX) {
    return m_count;
  } else {
    uint64_t next_val = m_head->GetValueAsUnsigned(0);
    uint64_t prev_val = m_tail->GetValueAsUnsigned(0);
    if (next_val == 0 || prev_val == 0)
      return 0;
    if (next_val == m_node_address)
      return 0;
    if (next_val == prev_val)
      return 1;
    uint64_t size = 2;
    ListEntry current(m_head);
    while (current.next() && current.next().value() != m_node_address) {
      size++;
      current = current.next();
      if (size > m_list_capping_size)
        break;
    }
    return m_count = (size - 1);
  }
}

lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(size_t idx) {
  static ConstString g_value("__value_");
  static ConstString g_next("__next_");

  if (idx >= CalculateNumChildren())
    return lldb::ValueObjectSP();

  if (!m_head || !m_tail || m_node_address == 0)
    return lldb::ValueObjectSP();

  if (HasLoop(idx + 1))
    return lldb::ValueObjectSP();

  ValueObjectSP current_sp = GetItem(idx);
  if (!current_sp)
    return lldb::ValueObjectSP();

  current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
  if (!current_sp)
    return lldb::ValueObjectSP();

  if (current_sp->GetName() == g_next) {
    ProcessSP process_sp(current_sp->GetProcessSP());
    if (!process_sp)
      return nullptr;

    // if we grabbed the __next_ pointer, then the child is one pointer deep-er
    lldb::addr_t addr = current_sp->GetParent()->GetPointerValue();
    addr = addr + 2 * process_sp->GetAddressByteSize();
    ExecutionContext exe_ctx(process_sp);
    current_sp =
        CreateValueObjectFromAddress("__value_", addr, exe_ctx, m_element_type);
  }

  // we need to copy current_sp into a new object otherwise we will end up with
  // all items named __value_
  DataExtractor data;
  Status error;
  current_sp->GetData(data, error);
  if (error.Fail())
    return lldb::ValueObjectSP();

  StreamString name;
  name.Printf("[%" PRIu64 "]", (uint64_t)idx);
  return CreateValueObjectFromData(name.GetString(), data,
                                   m_backend.GetExecutionContextRef(),
                                   m_element_type);
}

bool ListFrontEnd::Update() {
  AbstractListFrontEnd::Update();
  m_tail = nullptr;
  m_node_address = 0;

  Status err;
  ValueObjectSP backend_addr(m_backend.AddressOf(err));
  if (err.Fail() || !backend_addr)
    return false;
  m_node_address = backend_addr->GetValueAsUnsigned(0);
  if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS)
    return false;
  ValueObjectSP impl_sp(
      m_backend.GetChildMemberWithName(ConstString("__end_"), true));
  if (!impl_sp)
    return false;
  m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
  m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get();
  return false;
}

SyntheticChildrenFrontEnd *formatters::LibcxxStdListSyntheticFrontEndCreator(
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
  return (valobj_sp ? new ListFrontEnd(valobj_sp) : nullptr);
}

SyntheticChildrenFrontEnd *
formatters::LibcxxStdForwardListSyntheticFrontEndCreator(
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
  return valobj_sp ? new ForwardListFrontEnd(*valobj_sp) : nullptr;
}
<commit_msg>Check the result of creating a node from __next_ in the std::list formatter.<commit_after>//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "LibCxx.h"

#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

namespace {

class ListEntry {
public:
  ListEntry() = default;
  ListEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
  ListEntry(const ListEntry &rhs) = default;
  ListEntry(ValueObject *entry)
      : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}

  ListEntry next() {
    static ConstString g_next("__next_");

    if (!m_entry_sp)
      return ListEntry();
    return ListEntry(m_entry_sp->GetChildMemberWithName(g_next, true));
  }

  ListEntry prev() {
    static ConstString g_prev("__prev_");

    if (!m_entry_sp)
      return ListEntry();
    return ListEntry(m_entry_sp->GetChildMemberWithName(g_prev, true));
  }

  uint64_t value() const {
    if (!m_entry_sp)
      return 0;
    return m_entry_sp->GetValueAsUnsigned(0);
  }

  bool null() { return (value() == 0); }

  explicit operator bool() { return GetEntry() && !null(); }

  ValueObjectSP GetEntry() { return m_entry_sp; }

  void SetEntry(ValueObjectSP entry) { m_entry_sp = entry; }

  bool operator==(const ListEntry &rhs) const { return value() == rhs.value(); }

  bool operator!=(const ListEntry &rhs) const { return !(*this == rhs); }

private:
  ValueObjectSP m_entry_sp;
};

class ListIterator {
public:
  ListIterator() = default;
  ListIterator(ListEntry entry) : m_entry(entry) {}
  ListIterator(ValueObjectSP entry) : m_entry(entry) {}
  ListIterator(const ListIterator &rhs) = default;
  ListIterator(ValueObject *entry) : m_entry(entry) {}

  ValueObjectSP value() { return m_entry.GetEntry(); }

  ValueObjectSP advance(size_t count) {
    if (count == 0)
      return m_entry.GetEntry();
    if (count == 1) {
      next();
      return m_entry.GetEntry();
    }
    while (count > 0) {
      next();
      count--;
      if (m_entry.null())
        return lldb::ValueObjectSP();
    }
    return m_entry.GetEntry();
  }

  bool operator==(const ListIterator &rhs) const {
    return (rhs.m_entry == m_entry);
  }

protected:
  void next() { m_entry = m_entry.next(); }

  void prev() { m_entry = m_entry.prev(); }

private:
  ListEntry m_entry;
};

class AbstractListFrontEnd : public SyntheticChildrenFrontEnd {
public:
  size_t GetIndexOfChildWithName(ConstString name) override {
    return ExtractIndexFromString(name.GetCString());
  }
  bool MightHaveChildren() override { return true; }
  bool Update() override;

protected:
  AbstractListFrontEnd(ValueObject &valobj)
      : SyntheticChildrenFrontEnd(valobj) {}

  size_t m_count;
  ValueObject *m_head;

  static constexpr bool g_use_loop_detect = true;
  size_t m_loop_detected; // The number of elements that have had loop detection
                          // run over them.
  ListEntry m_slow_runner; // Used for loop detection
  ListEntry m_fast_runner; // Used for loop detection

  size_t m_list_capping_size;
  CompilerType m_element_type;
  std::map<size_t, ListIterator> m_iterators;

  bool HasLoop(size_t count);
  ValueObjectSP GetItem(size_t idx);
};

class ForwardListFrontEnd : public AbstractListFrontEnd {
public:
  ForwardListFrontEnd(ValueObject &valobj);

  size_t CalculateNumChildren() override;
  ValueObjectSP GetChildAtIndex(size_t idx) override;
  bool Update() override;
};

class ListFrontEnd : public AbstractListFrontEnd {
public:
  ListFrontEnd(lldb::ValueObjectSP valobj_sp);

  ~ListFrontEnd() override = default;

  size_t CalculateNumChildren() override;

  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

  bool Update() override;

private:
  lldb::addr_t m_node_address;
  ValueObject *m_tail;
};

} // end anonymous namespace

bool AbstractListFrontEnd::Update() {
  m_loop_detected = 0;
  m_count = UINT32_MAX;
  m_head = nullptr;
  m_list_capping_size = 0;
  m_slow_runner.SetEntry(nullptr);
  m_fast_runner.SetEntry(nullptr);
  m_iterators.clear();

  if (m_backend.GetTargetSP())
    m_list_capping_size =
        m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
  if (m_list_capping_size == 0)
    m_list_capping_size = 255;

  CompilerType list_type = m_backend.GetCompilerType();
  if (list_type.IsReferenceType())
    list_type = list_type.GetNonReferenceType();

  if (list_type.GetNumTemplateArguments() == 0)
    return false;
  m_element_type = list_type.GetTypeTemplateArgument(0);

  return false;
}

bool AbstractListFrontEnd::HasLoop(size_t count) {
  if (!g_use_loop_detect)
    return false;
  // don't bother checking for a loop if we won't actually need to jump nodes
  if (m_count < 2)
    return false;

  if (m_loop_detected == 0) {
    // This is the first time we are being run (after the last update). Set up
    // the loop invariant for the first element.
    m_slow_runner = ListEntry(m_head).next();
    m_fast_runner = m_slow_runner.next();
    m_loop_detected = 1;
  }

  // Loop invariant:
  // Loop detection has been run over the first m_loop_detected elements. If
  // m_slow_runner == m_fast_runner then the loop has been detected after
  // m_loop_detected elements.
  const size_t steps_to_run = std::min(count, m_count);
  while (m_loop_detected < steps_to_run && m_slow_runner && m_fast_runner &&
         m_slow_runner != m_fast_runner) {

    m_slow_runner = m_slow_runner.next();
    m_fast_runner = m_fast_runner.next().next();
    m_loop_detected++;
  }
  if (count <= m_loop_detected)
    return false; // No loop in the first m_loop_detected elements.
  if (!m_slow_runner || !m_fast_runner)
    return false; // Reached the end of the list. Definitely no loops.
  return m_slow_runner == m_fast_runner;
}

ValueObjectSP AbstractListFrontEnd::GetItem(size_t idx) {
  size_t advance = idx;
  ListIterator current(m_head);
  if (idx > 0) {
    auto cached_iterator = m_iterators.find(idx - 1);
    if (cached_iterator != m_iterators.end()) {
      current = cached_iterator->second;
      advance = 1;
    }
  }
  ValueObjectSP value_sp = current.advance(advance);
  m_iterators[idx] = current;
  return value_sp;
}

ForwardListFrontEnd::ForwardListFrontEnd(ValueObject &valobj)
    : AbstractListFrontEnd(valobj) {
  Update();
}

size_t ForwardListFrontEnd::CalculateNumChildren() {
  if (m_count != UINT32_MAX)
    return m_count;

  ListEntry current(m_head);
  m_count = 0;
  while (current && m_count < m_list_capping_size) {
    ++m_count;
    current = current.next();
  }
  return m_count;
}

ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) {
  if (idx >= CalculateNumChildren())
    return nullptr;

  if (!m_head)
    return nullptr;

  if (HasLoop(idx + 1))
    return nullptr;

  ValueObjectSP current_sp = GetItem(idx);
  if (!current_sp)
    return nullptr;

  current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
  if (!current_sp)
    return nullptr;

  // we need to copy current_sp into a new object otherwise we will end up with
  // all items named __value_
  DataExtractor data;
  Status error;
  current_sp->GetData(data, error);
  if (error.Fail())
    return nullptr;

  return CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data,
                                   m_backend.GetExecutionContextRef(),
                                   m_element_type);
}

static ValueObjectSP GetValueOfCompressedPair(ValueObject &pair) {
  ValueObjectSP value = pair.GetChildMemberWithName(ConstString("__value_"), true);
  if (! value) {
    // pre-r300140 member name
    value = pair.GetChildMemberWithName(ConstString("__first_"), true);
  }
  return value;
}

bool ForwardListFrontEnd::Update() {
  AbstractListFrontEnd::Update();

  Status err;
  ValueObjectSP backend_addr(m_backend.AddressOf(err));
  if (err.Fail() || !backend_addr)
    return false;

  ValueObjectSP impl_sp(
      m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true));
  if (!impl_sp)
    return false;
  impl_sp = GetValueOfCompressedPair(*impl_sp);
  if (!impl_sp)
    return false;
  m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
  return false;
}

ListFrontEnd::ListFrontEnd(lldb::ValueObjectSP valobj_sp)
    : AbstractListFrontEnd(*valobj_sp), m_node_address(), m_tail(nullptr) {
  if (valobj_sp)
    Update();
}

size_t ListFrontEnd::CalculateNumChildren() {
  if (m_count != UINT32_MAX)
    return m_count;
  if (!m_head || !m_tail || m_node_address == 0)
    return 0;
  ValueObjectSP size_alloc(
      m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
  if (size_alloc) {
    ValueObjectSP value = GetValueOfCompressedPair(*size_alloc);
    if (value) {
      m_count = value->GetValueAsUnsigned(UINT32_MAX);
    }
  }
  if (m_count != UINT32_MAX) {
    return m_count;
  } else {
    uint64_t next_val = m_head->GetValueAsUnsigned(0);
    uint64_t prev_val = m_tail->GetValueAsUnsigned(0);
    if (next_val == 0 || prev_val == 0)
      return 0;
    if (next_val == m_node_address)
      return 0;
    if (next_val == prev_val)
      return 1;
    uint64_t size = 2;
    ListEntry current(m_head);
    while (current.next() && current.next().value() != m_node_address) {
      size++;
      current = current.next();
      if (size > m_list_capping_size)
        break;
    }
    return m_count = (size - 1);
  }
}

lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(size_t idx) {
  static ConstString g_value("__value_");
  static ConstString g_next("__next_");

  if (idx >= CalculateNumChildren())
    return lldb::ValueObjectSP();

  if (!m_head || !m_tail || m_node_address == 0)
    return lldb::ValueObjectSP();

  if (HasLoop(idx + 1))
    return lldb::ValueObjectSP();

  ValueObjectSP current_sp = GetItem(idx);
  if (!current_sp)
    return lldb::ValueObjectSP();

  current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
  if (!current_sp)
    return lldb::ValueObjectSP();

  if (current_sp->GetName() == g_next) {
    ProcessSP process_sp(current_sp->GetProcessSP());
    if (!process_sp)
      return lldb::ValueObjectSP();

    // if we grabbed the __next_ pointer, then the child is one pointer deep-er
    lldb::addr_t addr = current_sp->GetParent()->GetPointerValue();
    addr = addr + 2 * process_sp->GetAddressByteSize();
    ExecutionContext exe_ctx(process_sp);
    current_sp =
        CreateValueObjectFromAddress("__value_", addr, exe_ctx, m_element_type);
    if (!current_sp)
      return lldb::ValueObjectSP();
  }

  // we need to copy current_sp into a new object otherwise we will end up with
  // all items named __value_
  DataExtractor data;
  Status error;
  current_sp->GetData(data, error);
  if (error.Fail())
    return lldb::ValueObjectSP();

  StreamString name;
  name.Printf("[%" PRIu64 "]", (uint64_t)idx);
  return CreateValueObjectFromData(name.GetString(), data,
                                   m_backend.GetExecutionContextRef(),
                                   m_element_type);
}

bool ListFrontEnd::Update() {
  AbstractListFrontEnd::Update();
  m_tail = nullptr;
  m_node_address = 0;

  Status err;
  ValueObjectSP backend_addr(m_backend.AddressOf(err));
  if (err.Fail() || !backend_addr)
    return false;
  m_node_address = backend_addr->GetValueAsUnsigned(0);
  if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS)
    return false;
  ValueObjectSP impl_sp(
      m_backend.GetChildMemberWithName(ConstString("__end_"), true));
  if (!impl_sp)
    return false;
  m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
  m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get();
  return false;
}

SyntheticChildrenFrontEnd *formatters::LibcxxStdListSyntheticFrontEndCreator(
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
  return (valobj_sp ? new ListFrontEnd(valobj_sp) : nullptr);
}

SyntheticChildrenFrontEnd *
formatters::LibcxxStdForwardListSyntheticFrontEndCreator(
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
  return valobj_sp ? new ForwardListFrontEnd(*valobj_sp) : nullptr;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#ifndef __BASE_REFCNT_HH__
#define __BASE_REFCNT_HH__

class RefCounted
{
  private:
    int count;

  private:
    // Don't allow a default copy constructor or copy operator on
    // these objects because the default operation will copy the
    // reference count as well and we certainly don't want that.
    RefCounted(const RefCounted &);
    RefCounted &operator=(const RefCounted &);

  public:
    RefCounted() : count(0) {}
    virtual ~RefCounted() {}

    void incref() { ++count; }
    void decref() { if (--count <= 0) delete this; }
};

template <class T>
class RefCountingPtr
{
  protected:
    T *data;

    void copy(T *d)
    {
        data = d;
        if (data)
            data->incref();
    }
    void del()
    {
        if (data)
            data->decref();
    }
    void set(T *d)
    {
        if (data == d)
            return;

        del();
        copy(d);
    }

  public:
    RefCountingPtr() : data(0) {}
    RefCountingPtr(T *data) { copy(data); }
    RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }
    ~RefCountingPtr() { del(); }

    T *operator->() { return data; }
    T &operator*() { return *data; }
    T *get() { return data; }

    const T *operator->() const { return data; }
    const T &operator*() const { return *data; }
    const T *get() const { return data; }

    const RefCountingPtr &operator=(T *p) { set(p); return *this; }
    const RefCountingPtr &operator=(const RefCountingPtr &r)
    { return operator=(r.data); }

    bool operator!() const { return data == 0; }
    operator bool() const { return data != 0; }
};

template<class T>
bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() == r.get(); }

template<class T>
bool operator==(const RefCountingPtr<T> &l, const T *r)
{ return l.get() == r; }

template<class T>
bool operator==(const T *l, const RefCountingPtr<T> &r)
{ return l == r.get(); }

template<class T>
bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() != r.get(); }

template<class T>
bool operator!=(const RefCountingPtr<T> &l, const T *r)
{ return l.get() != r; }

template<class T>
bool operator!=(const T *l, const RefCountingPtr<T> &r)
{ return l != r.get(); }

#endif // __BASE_REFCNT_HH__
<commit_msg>refcnt: Change things around so that we handle constness correctly. To use a non const pointer: typedef RefCountingPtr<Foo> FooPtr;<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#ifndef __BASE_REFCNT_HH__
#define __BASE_REFCNT_HH__

class RefCounted
{
  private:
    mutable int count;

  private:
    // Don't allow a default copy constructor or copy operator on
    // these objects because the default operation will copy the
    // reference count as well and we certainly don't want that.
    RefCounted(const RefCounted &);
    RefCounted &operator=(const RefCounted &);

  public:
    RefCounted() : count(0) {}
    virtual ~RefCounted() {}

    void incref() { ++count; }
    void decref() { if (--count <= 0) delete this; }
};

template <class T>
class RefCountingPtr
{
  protected:
    T *data;

    void copy(T *d)
    {
        data = d;
        if (data)
            data->incref();
    }
    void del()
    {
        if (data)
            data->decref();
    }
    void set(T *d)
    {
        if (data == d)
            return;

        del();
        copy(d);
    }

  public:
    RefCountingPtr() : data(0) {}
    RefCountingPtr(T *data) { copy(data); }
    RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }
    ~RefCountingPtr() { del(); }

    T *operator->() const { return data; }
    T &operator*() const { return *data; }
    T *get() const { return data; }

    const RefCountingPtr &operator=(T *p) { set(p); return *this; }
    const RefCountingPtr &operator=(const RefCountingPtr &r)
    { return operator=(r.data); }

    bool operator!() const { return data == 0; }
    operator bool() const { return data != 0; }
};

template<class T>
bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() == r.get(); }

template<class T>
bool operator==(const RefCountingPtr<T> &l, const T *r)
{ return l.get() == r; }

template<class T>
bool operator==(const T *l, const RefCountingPtr<T> &r)
{ return l == r.get(); }

template<class T>
bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() != r.get(); }

template<class T>
bool operator!=(const RefCountingPtr<T> &l, const T *r)
{ return l.get() != r; }

template<class T>
bool operator!=(const T *l, const RefCountingPtr<T> &r)
{ return l != r.get(); }

#endif // __BASE_REFCNT_HH__
<|endoftext|>


<commit_before>//============================================================================
// Name        : benchpress.cpp
// Author      : Ulrik Kofoed Pedersen
// Version     :
// Copyright   : MIT. See LICENSE file.
// Description : Use blosc with different algorithms to compress data from
//               datasets in an HDF5 file - and benchmark the performance
//============================================================================

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <sstream>
using namespace std;

#include <blosc.h>
#include <hdf5.h>
#include <hdf5_hl.h>

#include <boost/program_options.hpp>
#include <boost/timer/timer.hpp>
namespace po = boost::program_options;

class Image {
public:
    Image() : pdata(NULL), bytes(0), typesize(0){};
    Image(unsigned int width, unsigned int height, int bpp, void* pdata);
    Image(unsigned int nbytes, void* pdata);
    Image(const Image& src);     // copy constructor
    void next(const Image& src); // Increment pointer to next image after src
    void next();                 // Increment pointer to next image position
    // Operators
    Image& operator=( const Image& src );
    const void* data_ptr();
    unsigned int frame_bytes() {return this->bytes;}
    size_t get_typesize(){return this->typesize;}
private:
    void * pdata;
    unsigned int bytes;
    size_t typesize;
};

void * read_dataset(const string& file_name,
        const string& dataset_name, vector<Image>& images);
vector<string> &split_string(const string &s, char delim, vector<string> &elems);

vector<string> &split_string(const string &s, char delim, vector<string> &elems) {
    stringstream ss(s);
    string item;
    while (getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

void * read_dataset(const string& file_name,
        const string& dataset_name, vector<Image>& images)
{
    herr_t herr;
    int rank=0;
    H5T_class_t class_id;
    size_t type_size;
    hid_t file;

    file = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);

    herr = H5LTget_dataset_ndims(file, dataset_name.c_str(), &rank);
    hsize_t *dims = (hsize_t*)calloc(rank, sizeof(hsize_t));

    herr = H5LTget_dataset_info(file, dataset_name.c_str(), dims, &class_id, &type_size);

    unsigned int dset_pixels = 1;
    for (int i=0;i<rank; i++) dset_pixels *= dims[i];

    void * pdata = calloc(dset_pixels, type_size);
    herr = H5LTread_dataset_int(file, dataset_name.c_str(), (int*)pdata);

    // Create a list of images and push it to the user supplied 'images' vector
    unsigned int frame_pixels = 1;
    for (int i = 1; i<rank; i++) frame_pixels *= dims[i];
    Image img(frame_pixels * type_size, pdata);
    for (unsigned int i = 0; i<dims[0]; i++)
    {
        images.push_back(img);
        img.next();
    }

    free(dims);
    herr = H5Fclose(file);
    return pdata;
}

Image::Image(unsigned int width, unsigned int height, int bpp, void* pdata)
 : pdata(pdata), typesize(bpp)
{
    this->bytes = width * height * bpp;
}

Image::Image(unsigned int nbytes, void* pdata)
 : pdata(pdata), bytes(nbytes), typesize(4)
{
}

Image::Image(const Image& src)
{
    this->bytes = src.bytes;
    this->pdata = src.pdata;
    this->typesize = src.typesize;
}

void Image::next(const Image& src)
{
    this->pdata = (char*)(src.pdata) + src.bytes;
}

void Image::next()
{
    this->next(*this);
}

Image& Image::operator=( const Image& src )
{
    if (this != &src) {
        this->bytes = src.bytes;
        this->pdata = src.pdata;
        this->typesize = src.typesize;
    }
    return *this;
}

const void* Image::data_ptr()
{
    return this->pdata;
}

int main(int argc, char* argv[]) {
    int threads;
    int compress_level;
    int shuffle;
    string algorithm;
    po::options_description opt_desc("Available options");
    po::variables_map var_map;
    const char * compression_algorithms = blosc_list_compressors();

    // Handle CLI options and arguments
    try {
    opt_desc.add_options()
            ("help,h", "Show online help")
            ("algorithm,a", po::value< string >(&algorithm)->default_value("blosclz"), compression_algorithms)
            ("threads,t", po::value<int>(&threads)->default_value(1), "Number of threads to use")
            ("level,l", po::value<int>(&compress_level)->default_value(0), "Compression level [0..9]")
            ("shuffle,s", po::value<int>(&shuffle)->default_value(1), "Precondition shuffle")
            ("list", "List available compression algorithms")
            ("file", po::value< string >()->default_value(""), "Input file")
            ("dataset", po::value<string>()->default_value(""), "Input dataset")
    ;

    po::positional_options_description p;
    p.add("file", 1);     // Input file name
    p.add("dataset", 1);  // Input dataset (inside file)

    po::store(po::command_line_parser(argc, argv).options(opt_desc).positional(p).run(), var_map);
    po::notify(var_map);

    if (var_map.count("help")) {
        cout << opt_desc << "\n" << endl;
        return 1;
    }

    if (var_map.count("list")) {
        vector<string> algo_list;
        split_string(string (compression_algorithms), ',', algo_list);
        cout << "Available compression algorithms:" << endl;
        vector<string>::iterator it;
        for (it = algo_list.begin(); it != algo_list.end(); ++it)
        {
            char * complib;
            char * complib_version;
            blosc_get_complib_info(const_cast<char*>( it->c_str() ), &complib, &complib_version);
            cout << "\t" << it->c_str() << "\t" << complib_version << "\t" << complib << endl;
            free(complib); free(complib_version);
        }
        return -1;
    }

    cout << "Reading from file: " << var_map["file"].as<string>() << endl;
    cout << "Input dataset:     " << var_map["dataset"].as<string>() << endl;
    }
    catch (std::exception& e) // Catch option parsing exceptions
    {
        cout << "Option parsing exception: " << endl;
        cout << "\t boost error: \"" << e.what() << "\"" << endl;
        cout << "\n" << opt_desc << endl;
        return 1;
    }

    // Read the input images from the file/dataset and push
    // into the images vector
    vector<Image> images;
    void * pdata = read_dataset(var_map["file"].as<string>(),
            var_map["dataset"].as<string>(), images);

    cout << "Number of images read: " << images.size() << endl;

    // Initialise blosc and configure number of threads and algorithm
    blosc_init();
    blosc_set_nthreads(threads);
    blosc_set_compressor(algorithm.c_str());
    size_t dest_size = images[0].frame_bytes() + BLOSC_MAX_OVERHEAD;
    void * dest_buf = calloc(dest_size, sizeof(char));

    // Loop through the vector of frames, compress each one and time the loop.
    // The compressed data is not used - but the buffer is reused for next iteration
    vector<Image>::iterator it;
    for (it = images.begin(); it != images.end(); ++it)
    {
        boost::timer::auto_cpu_timer timer;
        //cout << static_cast<const int*>(it->data_ptr())[0] << endl;
        int cbytes = blosc_compress(compress_level, shuffle,
                it->get_typesize(),it->frame_bytes(), it->data_ptr(),
                dest_buf, dest_size);
        double ratio = (double)cbytes/(double)(it->frame_bytes());
        cout << "ratio: " << 1./ratio << " (" << cbytes << "/" << it->frame_bytes() << ")";
        cout << " rate: " << endl;
    }

    blosc_destroy();
    free (pdata);
    free(dest_buf);
    return 0;
}
<commit_msg>Adding summary report of performance at end of run<commit_after>//============================================================================
// Name        : benchpress.cpp
// Author      : Ulrik Kofoed Pedersen
// Version     :
// Copyright   : MIT. See LICENSE file.
// Description : Use blosc with different algorithms to compress data from
//               datasets in an HDF5 file - and benchmark the performance
//============================================================================

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <sstream>
using namespace std;

#include <blosc.h>
#include <hdf5.h>
#include <hdf5_hl.h>

#include <boost/program_options.hpp>
#include <boost/timer/timer.hpp>
namespace po = boost::program_options;
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;

class Image {
public:
    Image() : pdata(NULL), bytes(0), typesize(0){};
    Image(unsigned int width, unsigned int height, int bpp, void* pdata);
    Image(unsigned int nbytes, void* pdata);
    Image(const Image& src);     // copy constructor
    void next(const Image& src); // Increment pointer to next image after src
    void next();                 // Increment pointer to next image position
    // Operators
    Image& operator=( const Image& src );
    const void* data_ptr();
    unsigned int frame_bytes() {return this->bytes;}
    size_t get_typesize(){return this->typesize;}
private:
    void * pdata;
    unsigned int bytes;
    size_t typesize;
};

void * read_dataset(const string& file_name,
        const string& dataset_name, vector<Image>& images);
vector<string> &split_string(const string &s, char delim, vector<string> &elems);

vector<string> &split_string(const string &s, char delim, vector<string> &elems) {
    stringstream ss(s);
    string item;
    while (getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

void * read_dataset(const string& file_name,
        const string& dataset_name, vector<Image>& images)
{
    herr_t herr;
    int rank=0;
    H5T_class_t class_id;
    size_t type_size;
    hid_t file;

    file = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);

    herr = H5LTget_dataset_ndims(file, dataset_name.c_str(), &rank);
    hsize_t *dims = (hsize_t*)calloc(rank, sizeof(hsize_t));

    herr = H5LTget_dataset_info(file, dataset_name.c_str(), dims, &class_id, &type_size);

    unsigned int dset_pixels = 1;
    for (int i=0;i<rank; i++) dset_pixels *= dims[i];

    void * pdata = calloc(dset_pixels, type_size);
    herr = H5LTread_dataset_int(file, dataset_name.c_str(), (int*)pdata);

    // Create a list of images and push it to the user supplied 'images' vector
    unsigned int frame_pixels = 1;
    for (int i = 1; i<rank; i++) frame_pixels *= dims[i];
    Image img(frame_pixels * type_size, pdata);
    for (unsigned int i = 0; i<dims[0]; i++)
    {
        images.push_back(img);
        img.next();
    }

    free(dims);
    herr = H5Fclose(file);
    return pdata;
}

Image::Image(unsigned int width, unsigned int height, int bpp, void* pdata)
 : pdata(pdata), typesize(bpp)
{
    this->bytes = width * height * bpp;
}

Image::Image(unsigned int nbytes, void* pdata)
 : pdata(pdata), bytes(nbytes), typesize(4)
{
}

Image::Image(const Image& src)
{
    this->bytes = src.bytes;
    this->pdata = src.pdata;
    this->typesize = src.typesize;
}

void Image::next(const Image& src)
{
    this->pdata = (char*)(src.pdata) + src.bytes;
}

void Image::next()
{
    this->next(*this);
}

Image& Image::operator=( const Image& src )
{
    if (this != &src) {
        this->bytes = src.bytes;
        this->pdata = src.pdata;
        this->typesize = src.typesize;
    }
    return *this;
}

const void* Image::data_ptr()
{
    return this->pdata;
}

int main(int argc, char* argv[]) {
    int threads;
    int compress_level;
    int shuffle;
    string algorithm;
    po::options_description opt_desc("Available options");
    po::variables_map var_map;
    const char * compression_algorithms = blosc_list_compressors();

    // Handle CLI options and arguments
    try {
    opt_desc.add_options()
            ("help,h", "Show online help")
            ("algorithm,a", po::value< string >(&algorithm)->default_value("blosclz"), compression_algorithms)
            ("threads,t", po::value<int>(&threads)->default_value(1), "Number of threads to use")
            ("level,l", po::value<int>(&compress_level)->default_value(0), "Compression level [0..9]")
            ("shuffle,s", po::value<int>(&shuffle)->default_value(1), "Precondition shuffle")
            ("list", "List available compression algorithms")
            ("file", po::value< string >()->default_value(""), "Input file")
            ("dataset", po::value<string>()->default_value(""), "Input dataset")
    ;

    po::positional_options_description p;
    p.add("file", 1);     // Input file name
    p.add("dataset", 1);  // Input dataset (inside file)

    po::store(po::command_line_parser(argc, argv).options(opt_desc).positional(p).run(), var_map);
    po::notify(var_map);

    if (var_map.count("help")) {
        cout << opt_desc << "\n" << endl;
        return 1;
    }

    if (var_map.count("list")) {
        vector<string> algo_list;
        split_string(string (compression_algorithms), ',', algo_list);
        cout << "Available compression algorithms:" << endl;
        vector<string>::iterator it;
        for (it = algo_list.begin(); it != algo_list.end(); ++it)
        {
            char * complib;
            char * complib_version;
            blosc_get_complib_info(const_cast<char*>( it->c_str() ), &complib, &complib_version);
            cout << "\t" << it->c_str() << "\t" << complib_version << "\t" << complib << endl;
            free(complib); free(complib_version);
        }
        return -1;
    }

    cout << "Reading from file: " << var_map["file"].as<string>() << endl;
    cout << "Input dataset:     " << var_map["dataset"].as<string>() << endl;
    }
    catch (std::exception& e) // Catch option parsing exceptions
    {
        cout << "Option parsing exception: " << endl;
        cout << "\t boost error: \"" << e.what() << "\"" << endl;
        cout << "\n" << opt_desc << endl;
        return 1;
    }

    // Read the input images from the file/dataset and push
    // into the images vector
    vector<Image> images;
    void * pdata = read_dataset(var_map["file"].as<string>(),
            var_map["dataset"].as<string>(), images);

    cout << "Number of images read: " << images.size() << endl;

    // Initialise blosc and configure number of threads and algorithm
    blosc_init();
    blosc_set_nthreads(threads);
    blosc_set_compressor(algorithm.c_str());
    size_t dest_size = images[0].frame_bytes() + BLOSC_MAX_OVERHEAD;
    void * dest_buf = calloc(dest_size, sizeof(char));

    // Loop through the vector of frames, compress each one and time the loop.
    // The compressed data is not used - but the buffer is reused for next iteration
    vector<cpu_times> elapsed_times;
    cpu_timer timer;

    vector<Image>::iterator it;
    unsigned long total_cbytes = 0;
    for (it = images.begin(); it != images.end(); ++it)
    {
        //cout << static_cast<const int*>(it->data_ptr())[0] << endl;
        int cbytes = blosc_compress(compress_level, shuffle,
                it->get_typesize(),it->frame_bytes(), it->data_ptr(),
                dest_buf, dest_size);
        total_cbytes += cbytes;
        double ratio = (double)cbytes/(double)(it->frame_bytes());
        cout << "ratio: " << 1./ratio << " (" << cbytes << "/" << it->frame_bytes() << ")";
        cout << " rate: " << endl;

        cpu_times wus_times = timer.elapsed();
        elapsed_times.push_back(wus_times);
        cout << "wall: " << wus_times.wall/1000000000. << endl;
    }
    timer.stop();
    cpu_times wus_final = timer.elapsed();

    double dset_megabyte = (images.size() * images[0].frame_bytes())/(1024.*1024.);
    double comp_megabyte = total_cbytes/(1024. * 1024.);
    double ratio = dset_megabyte/comp_megabyte;
    double data_rate = dset_megabyte/(wus_final.wall/1000000000.);

    cout << "Full dset time. Wall=" << wus_final.wall/1000000000.;
    cout << " User: " << wus_final.user/1000000000.;
    cout << " System: " << wus_final.system/1000000000. << endl;
    cout << " dset: " << dset_megabyte << "MB   comp: " << comp_megabyte << "MB" << endl;
    cout << "Ratio: " << ratio << " Data rate: " << data_rate << " MB/s" << endl;

    blosc_destroy();
    free (pdata);
    free(dest_buf);
    return 0;
}
<|endoftext|>


<commit_before>#include "mcc/cfg/static_call_graph.h"

#include <cassert>
#include <iterator>
#include <memory>
#include <ostream>
#include <typeinfo>
#include <vector>

#include "mcc/cfg/set_helper.h"
#include "mcc/tac/operator.h"

namespace mcc {
namespace cfg {

Scg::Scg(mcc::tac::Tac &tac) {
  auto functionMap = tac.getFunctionMap();
  auto graphIndex = std::map<std::string, VertexDescriptor>();
  std::string currentFunctionName;

  for (auto function : *functionMap) {
    auto vt = boost::add_vertex(function.second, graph);
    graphIndex.insert(std::make_pair(function.second->getName(), vt));
  }

  for (auto triple : tac.codeLines) {
    auto line = *triple;
    if (typeid(line) == typeid(Label)) {
      auto label = std::static_pointer_cast<Label>(triple);
      if (label->isFunctionEntry()) {
        currentFunctionName = label->getName();
      }
    } else if (triple->getOperator().getType() == OperatorType::CALL) {
      auto &arg1 = *(triple->getArg1());

      if (typeid(arg1) == typeid(Label)) {
        auto callTarget = std::static_pointer_cast<Label>(triple->getArg1());
        auto targetName = callTarget->getName();
        boost::add_edge(graphIndex[currentFunctionName], graphIndex[targetName],
                        graph);
      }
    }
  }
}

std::string Scg::toDot() const {
  std::ostringstream out;
  auto name = boost::make_transform_value_property_map(
      Name{}, boost::get(boost::vertex_bundle, graph));
  boost::write_graphviz(out, graph, boost::make_label_writer(name));
  return out.str();
}

void Scg::storeDot(std::string fileName) const {
  std::ofstream outf(fileName);
  outf << toDot();
}
}
}
<commit_msg>Fixed SCG type ID check<commit_after>#include "mcc/cfg/static_call_graph.h"

#include <cassert>
#include <iterator>
#include <memory>
#include <ostream>
#include <typeinfo>
#include <vector>

#include "mcc/cfg/set_helper.h"
#include "mcc/tac/operator.h"
#include "mcc/tac/helper/ast_converters.h"

namespace mcc {
namespace cfg {

Scg::Scg(mcc::tac::Tac &tac) {
  auto functionMap = tac.getFunctionMap();
  auto graphIndex = std::map<std::string, VertexDescriptor>();
  std::string currentFunctionName;

  for (auto function : *functionMap) {
    auto vt = boost::add_vertex(function.second, graph);
    graphIndex.insert(std::make_pair(function.second->getName(), vt));
  }

  for (auto triple : tac.codeLines) {
    if (mcc::tac::helper::isType<Label>(triple)) {
      auto label = std::static_pointer_cast<Label>(triple);
      if (label->isFunctionEntry()) {
        currentFunctionName = label->getName();
      }
    } else if (triple->getOperator().getType() == OperatorType::CALL) {
      if (mcc::tac::helper::isType<Label>(triple->getArg1())) {
        auto callTarget = std::static_pointer_cast<Label>(triple->getArg1());
        auto targetName = callTarget->getName();
        boost::add_edge(graphIndex[currentFunctionName], graphIndex[targetName],
                        graph);
      }
    }
  }
}

std::string Scg::toDot() const {
  std::ostringstream out;
  auto name = boost::make_transform_value_property_map(
      Name{}, boost::get(boost::vertex_bundle, graph));
  boost::write_graphviz(out, graph, boost::make_label_writer(name));
  return out.str();
}

void Scg::storeDot(std::string fileName) const {
  std::ofstream outf(fileName);
  outf << toDot();
}
}
}
<|endoftext|>