<commit_before>#include <QString>
#include "kernel.h"
#include "ilwistypes.h"

using namespace Ilwis;

QString TypeHelper::type2HumanReadable(IlwisTypes t)
{
    switch(t) {
    case  itRASTER:
        return TR("Raster Coverage");
    case  itPOLYGON:
        return TR("Polygon Coverage");
    case  itLINE:
        return TR("Line Coverage");
    case  itPOINT:
        return TR("Point Coverage");
    case  itPOINT+itLINE:
        return TR("Feature Coverage");
    case  itPOINT+itPOLYGON:
        return TR("Feature Coverage");
    case  itPOLYGON+itLINE:
        return TR("Feature Coverage");
    case  itNUMERICDOMAIN:
        return TR("Value Domain");
    case  itITEMDOMAIN:
        return TR("Item Domain");
    case  itCOLORDOMAIN:
        return TR("Color Domain");
    case  itCOORDSYSTEM:
        return TR("Coordinate System");
    case  itCONVENTIONALCOORDSYSTEM:
        return TR("Conventional CoordinateSystem");
    case itBOUNDSONLYCSY:
        return TR("BoundsOnly CoordinateSystem");
    case  itGEOREF:
        return TR("Georeference");
    case  itTABLE:
        return TR("Table");
    case  itPROJECTION:
        return TR("Projection");
    case  itELLIPSOID:
        return TR("Ellipsoid");
    case  itGEODETICDATUM:
        return TR("Geodetic Datum");
    case  itCATALOG:
        return TR("Catalog");
    case  itOPERATIONMETADATA:
        return TR("OperationMetaData");
    case  itREPRESENTATION:
        return TR("Representation");

        // nonilwisobjects
    case itENVELOPE:
        return TR("Envelope");
    case itBOOL:
        return TR("Boolean");
    case itBOUNDINGBOX:
        return TR("BoundingBox");
    case itRASTERSIZE:
        return TR("Raster Size");
    case itINT8:
        return TR("Signed Byte");
    case itUINT8:
        return TR("Byte");
    case itINT16:
        return TR("Integer 16-bit");
    case itUINT16:
        return TR("Positive 16-bit Integer");
    case itINT32:
        return TR("Integer 32-bit");
    case itUINT32:
        return TR("Positive 32-bit Integer");
    case itINT64:
        return TR("Integer 64-bit");
    case itUINT64:
        return TR("Positive 64-bit Integer");
    case itFLOAT:
        return TR("Floatingpoint 32-bit");
    case itDOUBLE:
        return TR("Floatingpoint 64-bit");
    case itVALUERANGE:
        return TR("ValueRange");
    case itSTRING:
        return TR("String");
    case itDATE:
        return TR("Date");
    case itTIME:
        return TR("Time");
    case itCOORDINATE:
        return TR("Coordinate");
    case itPIXEL:
        return TR("Pixel");
    case itBINARY:
        return TR("Binary");
    case itFILE:
        return TR("File");
    case itURL:
        return TR("Url");
    case itTHEMATICITEM:
        return TR("Thematic class");
    case itNAMEDITEM:
        return TR("Named Identifier");
    case itINDEXEDITEM:
        return TR("Indexed Identifier");
    case itNUMERICITEM:
        return TR("Numeric Interval");
    case itTIMEITEM:
        return TR("Time Interval");
    case itPALETTECOLOR:
        return TR("Palette Color");
    case itCONTINUOUSCOLOR:
        return TR("Color");
    case itSAMPLESET:
        return TR("Sample Set");
    case itCATALOGVIEW:
        return TR("CatalogView");
    case itCOLLECTION:
        return TR("Collection");
    case itBUFFER:
        return TR("Buffer");
    case itCOVERAGE:
        return TR("Coverage");
    case itFEATURE:
        return TR("Feature");
    case itDOMAIN:
        return TR("Domain");
    case itDATETIME:
        return TR("DateTime");
    case itINTEGER:
        return TR("Integer");
    case itPOSITIVEINTEGER:
        return TR("Positive Integer");\
    case itNUMBER:
        return TR("Number");
    case itDOMAINITEM:
        return TR("Domain Item");
    case itLOCATION:
        return TR("location");
    }
    return TR("?");

}

QString TypeHelper::type2name(IlwisTypes t)
{
    switch(t) {
    case  itRASTER:
        return TR("rastercoverage");
    case  itPOLYGON:
        return TR("polygoncoverage");
    case  itLINE:
        return TR("linecoverage");
    case  itPOINT:
        return TR("pointcoverage");
    case  itPOINT+itLINE:
        return TR("featurecoverage");
    case  itPOINT+itPOLYGON:
        return TR("featurecoverage");
    case  itPOLYGON+itLINE:
        return TR("featurecoverage");
    case  itNUMERICDOMAIN:
        return TR("numericdomain");
    case  itITEMDOMAIN:
        return TR("itemdomain");
    case  itCOLORDOMAIN:
        return TR("colordomain");
    case  itCOORDSYSTEM:
        return TR("coordinatesystem");
    case  itCONVENTIONALCOORDSYSTEM:
        return TR("conventionalcoordinatesystem");
    case itBOUNDSONLYCSY:
        return TR("boundsonlycoordinatesystem");
    case  itGEOREF:
        return TR("georeference");
    case  itTABLE:
        return TR("table");
    case  itPROJECTION:
        return TR("projection");
    case  itELLIPSOID:
        return TR("ellipsoid");
    case  itGEODETICDATUM:
        return TR("geodeticdatum");
    case  itCATALOG:
        return TR("catalog");
    case  itOPERATIONMETADATA:
        return TR("operationmetatadata");
    case itREPRESENTATION:
        return TR("representation");
        // nonilwisobjects
    case itENVELOPE:
        return TR("envelope");
    case itBOOL:
        return TR("boolean");
    case itBOUNDINGBOX:
        return TR("boundingbox");
    case itRASTERSIZE:
        return TR("rastersize");
    case itINT8:
        return TR("signedbyte");
    case itUINT8:
        return TR("byte");
    case itINT16:
        return TR("int16");
    case itUINT16:
        return TR("uint16");
    case itINT32:
        return TR("Int32");
    case itUINT32:
        return TR("uint32");
    case itINT64:
        return TR("Int64");
    case itUINT64:
        return TR("uint64");
    case itFLOAT:
        return TR("Real32");
    case itDOUBLE:
        return TR("Real64");
    case itVALUERANGE:
        return TR("valuerange");
    case itSTRING:
        return TR("string");
    case itDATE:
        return TR("date");
    case itTIME:
        return TR("time");
    case itCOORDINATE:
        return TR("coordinate");
    case itPIXEL:
        return TR("pixel");
    case itBINARY:
        return TR("binary");
    case itFILE:
        return TR("file");
    case itURL:
        return TR("url");
    case itTHEMATICITEM:
        return TR("thematicclass");
    case itNAMEDITEM:
        return TR("namedidentifier");
    case itINDEXEDITEM:
        return TR("indexidentifier");
    case itNUMERICITEM:
        return TR("numericinterval");
    case itTIMEITEM:
        return TR("timeinterval");
    case itPALETTECOLOR:
        return TR("palettecolor");
    case itCONTINUOUSCOLOR:
        return TR("color");
    case itSAMPLESET:
        return TR("sampleset");
    case itCATALOGVIEW:
        return TR("catalogview");
    case itCOLLECTION:
        return TR("collection");
    case itBUFFER:
        return TR("buffer");
    case itCOVERAGE:
        return TR("coverage");
    case itFEATURE:
        return TR("featurecoverage");
    case itDOMAIN:
        return TR("domain");
    case itDATETIME:
        return TR("datetime");
    case itINTEGER:
        return TR("int");
    case itPOSITIVEINTEGER:
        return TR("uint");\
    case itNUMBER:
        return TR("number");
    case itDOMAINITEM:
        return TR("domainitem");
    case itLOCATION:
        return TR("location");
    }
    return TR("?");

}
<commit_msg>added type to text translation<commit_after>#include <QString>
#include "kernel.h"
#include "ilwistypes.h"

using namespace Ilwis;

QString TypeHelper::type2HumanReadable(IlwisTypes t)
{
    switch(t) {
    case  itRASTER:
        return TR("Raster Coverage");
    case  itPOLYGON:
        return TR("Polygon Coverage");
    case  itLINE:
        return TR("Line Coverage");
    case  itPOINT:
        return TR("Point Coverage");
    case  itPOINT+itLINE:
        return TR("Feature Coverage");
    case  itPOINT+itPOLYGON:
        return TR("Feature Coverage");
    case  itPOLYGON+itLINE:
        return TR("Feature Coverage");
    case  itNUMERICDOMAIN:
        return TR("Value Domain");
    case itTEXTDOMAIN:
        return TR("Text Domain");
    case  itITEMDOMAIN:
        return TR("Item Domain");
    case  itCOLORDOMAIN:
        return TR("Color Domain");
    case  itCOORDSYSTEM:
        return TR("Coordinate System");
    case  itCONVENTIONALCOORDSYSTEM:
        return TR("Conventional CoordinateSystem");
    case itBOUNDSONLYCSY:
        return TR("BoundsOnly CoordinateSystem");
    case  itGEOREF:
        return TR("Georeference");
    case  itTABLE:
        return TR("Table");
    case  itPROJECTION:
        return TR("Projection");
    case  itELLIPSOID:
        return TR("Ellipsoid");
    case  itGEODETICDATUM:
        return TR("Geodetic Datum");
    case  itCATALOG:
        return TR("Catalog");
    case  itOPERATIONMETADATA:
        return TR("OperationMetaData");
    case  itREPRESENTATION:
        return TR("Representation");

        // nonilwisobjects
    case itENVELOPE:
        return TR("Envelope");
    case itBOOL:
        return TR("Boolean");
    case itBOUNDINGBOX:
        return TR("BoundingBox");
    case itRASTERSIZE:
        return TR("Raster Size");
    case itINT8:
        return TR("Signed Byte");
    case itUINT8:
        return TR("Byte");
    case itINT16:
        return TR("Integer 16-bit");
    case itUINT16:
        return TR("Positive 16-bit Integer");
    case itINT32:
        return TR("Integer 32-bit");
    case itUINT32:
        return TR("Positive 32-bit Integer");
    case itINT64:
        return TR("Integer 64-bit");
    case itUINT64:
        return TR("Positive 64-bit Integer");
    case itFLOAT:
        return TR("Floatingpoint 32-bit");
    case itDOUBLE:
        return TR("Floatingpoint 64-bit");
    case itVALUERANGE:
        return TR("ValueRange");
    case itSTRING:
        return TR("String");
    case itDATE:
        return TR("Date");
    case itTIME:
        return TR("Time");
    case itCOORDINATE:
        return TR("Coordinate");
    case itPIXEL:
        return TR("Pixel");
    case itBINARY:
        return TR("Binary");
    case itFILE:
        return TR("File");
    case itURL:
        return TR("Url");
    case itTHEMATICITEM:
        return TR("Thematic class");
    case itNAMEDITEM:
        return TR("Named Identifier");
    case itINDEXEDITEM:
        return TR("Indexed Identifier");
    case itNUMERICITEM:
        return TR("Numeric Interval");
    case itTIMEITEM:
        return TR("Time Interval");
    case itPALETTECOLOR:
        return TR("Palette Color");
    case itCONTINUOUSCOLOR:
        return TR("Color");
    case itSAMPLESET:
        return TR("Sample Set");
    case itCATALOGVIEW:
        return TR("CatalogView");
    case itCOLLECTION:
        return TR("Collection");
    case itBUFFER:
        return TR("Buffer");
    case itCOVERAGE:
        return TR("Coverage");
    case itFEATURE:
        return TR("Feature");
    case itDOMAIN:
        return TR("Domain");
    case itDATETIME:
        return TR("DateTime");
    case itINTEGER:
        return TR("Integer");
    case itPOSITIVEINTEGER:
        return TR("Positive Integer");\
    case itNUMBER:
        return TR("Number");
    case itDOMAINITEM:
        return TR("Domain Item");
    case itLOCATION:
        return TR("location");
    }
    return TR("?");

}

QString TypeHelper::type2name(IlwisTypes t)
{
    switch(t) {
    case  itRASTER:
        return TR("rastercoverage");
    case  itPOLYGON:
        return TR("polygoncoverage");
    case  itLINE:
        return TR("linecoverage");
    case  itPOINT:
        return TR("pointcoverage");
    case  itPOINT+itLINE:
        return TR("featurecoverage");
    case  itPOINT+itPOLYGON:
        return TR("featurecoverage");
    case  itPOLYGON+itLINE:
        return TR("featurecoverage");
    case  itNUMERICDOMAIN:
        return TR("numericdomain");
    case  itITEMDOMAIN:
        return TR("itemdomain");
    case  itCOLORDOMAIN:
        return TR("colordomain");
    case  itTEXTDOMAIN:
        return TR("textdomain");
    case  itCOORDSYSTEM:
        return TR("coordinatesystem");
    case  itCONVENTIONALCOORDSYSTEM:
        return TR("conventionalcoordinatesystem");
    case itBOUNDSONLYCSY:
        return TR("boundsonlycoordinatesystem");
    case  itGEOREF:
        return TR("georeference");
    case  itTABLE:
        return TR("table");
    case  itPROJECTION:
        return TR("projection");
    case  itELLIPSOID:
        return TR("ellipsoid");
    case  itGEODETICDATUM:
        return TR("geodeticdatum");
    case  itCATALOG:
        return TR("catalog");
    case  itOPERATIONMETADATA:
        return TR("operationmetatadata");
    case itREPRESENTATION:
        return TR("representation");
        // nonilwisobjects
    case itENVELOPE:
        return TR("envelope");
    case itBOOL:
        return TR("boolean");
    case itBOUNDINGBOX:
        return TR("boundingbox");
    case itRASTERSIZE:
        return TR("rastersize");
    case itINT8:
        return TR("signedbyte");
    case itUINT8:
        return TR("byte");
    case itINT16:
        return TR("int16");
    case itUINT16:
        return TR("uint16");
    case itINT32:
        return TR("Int32");
    case itUINT32:
        return TR("uint32");
    case itINT64:
        return TR("Int64");
    case itUINT64:
        return TR("uint64");
    case itFLOAT:
        return TR("Real32");
    case itDOUBLE:
        return TR("Real64");
    case itVALUERANGE:
        return TR("valuerange");
    case itSTRING:
        return TR("string");
    case itDATE:
        return TR("date");
    case itTIME:
        return TR("time");
    case itCOORDINATE:
        return TR("coordinate");
    case itPIXEL:
        return TR("pixel");
    case itBINARY:
        return TR("binary");
    case itFILE:
        return TR("file");
    case itURL:
        return TR("url");
    case itTHEMATICITEM:
        return TR("thematicclass");
    case itNAMEDITEM:
        return TR("namedidentifier");
    case itINDEXEDITEM:
        return TR("indexidentifier");
    case itNUMERICITEM:
        return TR("numericinterval");
    case itTIMEITEM:
        return TR("timeinterval");
    case itPALETTECOLOR:
        return TR("palettecolor");
    case itCONTINUOUSCOLOR:
        return TR("color");
    case itSAMPLESET:
        return TR("sampleset");
    case itCATALOGVIEW:
        return TR("catalogview");
    case itCOLLECTION:
        return TR("collection");
    case itBUFFER:
        return TR("buffer");
    case itCOVERAGE:
        return TR("coverage");
    case itFEATURE:
        return TR("featurecoverage");
    case itDOMAIN:
        return TR("domain");
    case itDATETIME:
        return TR("datetime");
    case itINTEGER:
        return TR("int");
    case itPOSITIVEINTEGER:
        return TR("uint");\
    case itNUMBER:
        return TR("number");
    case itDOMAINITEM:
        return TR("domainitem");
    case itLOCATION:
        return TR("location");
    }
    return TR("?");

}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE pshm_test

#include "plib.h"

#include <stdlib.h>
#include <time.h>
#include <boost/test/included/unit_test.hpp>

static void * shm_test_thread (void *arg)
{
	pint		i, rand_num;
	psize		shm_size;
	ppointer	addr;
	PShm		*shm;

	if (arg == NULL)
		p_uthread_exit (1);

	shm = (PShm *) arg;
	rand_num = rand () % 127;
	shm_size = p_shm_get_size (shm);
	addr = p_shm_get_address (shm);

	if (shm_size == 0 || addr == NULL)
		p_uthread_exit (1);

	if (!p_shm_lock (shm))
		p_uthread_exit (1);

	for (i = 0; i < shm_size; ++i)
		*(((pchar *) addr) + i) = (pchar) rand_num;

	if (!p_shm_unlock (shm))
		p_uthread_exit (1);

	p_uthread_exit (0);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (pshm_general_test)
{
	PShm		*shm = NULL, *shm2 = NULL;
	ppointer	addr, addr2;
	pint		i;

	BOOST_REQUIRE (p_shm_get_address (shm) == NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 0);

	shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READONLY);
	BOOST_REQUIRE (shm2 != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm2) == 1024);

	addr2 = p_shm_get_address (shm2);
	BOOST_REQUIRE (shm2 != NULL);

	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm));
		*(((pchar *) addr) + i) = 'a';
		BOOST_CHECK (p_shm_unlock (shm));
	}

	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm2));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'a');
		BOOST_CHECK (p_shm_unlock (shm2));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm));
		*(((pchar *) addr) + i) = 'b';
		BOOST_CHECK (p_shm_unlock (shm));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'c');
		BOOST_CHECK (p_shm_unlock (shm2));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'b');
		BOOST_CHECK (p_shm_unlock (shm2));
	}

	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block_2", 1024, P_SHM_ACCESS_READWRITE);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'b');
		BOOST_CHECK (p_shm_unlock (shm));
	}

	p_shm_free (shm);
	p_shm_free (shm2);
}

BOOST_AUTO_TEST_CASE (pshm_thread_test)
{
	PShm		*shm;
	PUThread	*thr1, *thr2, *thr3;
	ppointer	addr;
	pint		i, val;
	pboolean	test_ok;

	srand ((puint) time (NULL));

	shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024 * 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	thr1 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr1 != NULL);

	thr2 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr2 != NULL);

	thr3 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr3 != NULL);

	BOOST_CHECK (p_uthread_join (thr1) == 0);
	BOOST_CHECK (p_uthread_join (thr2) == 0);
	BOOST_CHECK (p_uthread_join (thr3) == 0);

	test_ok = TRUE;
	val = *((pchar *) addr);

	for (i = 1; i < 1024 * 1024; ++i)
		if (*(((pchar *) addr) + i) != val) {
			test_ok = FALSE;
			break;
		}

	BOOST_REQUIRE (test_ok == TRUE);

	p_uthread_free (thr1);
	p_uthread_free (thr2);
	p_uthread_free (thr3);
	p_shm_free (shm);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>tests: Fix PShm test behavior on POSIX systems<commit_after>#define BOOST_TEST_MODULE pshm_test

#include "plib.h"

#include <stdlib.h>
#include <time.h>
#include <boost/test/included/unit_test.hpp>

static void * shm_test_thread (void *arg)
{
	pint		i, rand_num;
	psize		shm_size;
	ppointer	addr;
	PShm		*shm;

	if (arg == NULL)
		p_uthread_exit (1);

	shm = (PShm *) arg;
	rand_num = rand () % 127;
	shm_size = p_shm_get_size (shm);
	addr = p_shm_get_address (shm);

	if (shm_size == 0 || addr == NULL)
		p_uthread_exit (1);

	if (!p_shm_lock (shm))
		p_uthread_exit (1);

	for (i = 0; i < shm_size; ++i)
		*(((pchar *) addr) + i) = (pchar) rand_num;

	if (!p_shm_unlock (shm))
		p_uthread_exit (1);

	p_uthread_exit (0);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (pshm_general_test)
{
	PShm		*shm = NULL, *shm2 = NULL;
	ppointer	addr, addr2;
	pint		i;

	BOOST_REQUIRE (p_shm_get_address (shm) == NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 0);

	shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READONLY);
	BOOST_REQUIRE (shm2 != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm2) == 1024);

	addr2 = p_shm_get_address (shm2);
	BOOST_REQUIRE (shm2 != NULL);

	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm));
		*(((pchar *) addr) + i) = 'a';
		BOOST_CHECK (p_shm_unlock (shm));
	}

	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm2));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'a');
		BOOST_CHECK (p_shm_unlock (shm2));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm));
		*(((pchar *) addr) + i) = 'b';
		BOOST_CHECK (p_shm_unlock (shm));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'c');
		BOOST_CHECK (p_shm_unlock (shm2));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'b');
		BOOST_CHECK (p_shm_unlock (shm2));
	}

	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block_2", 1024, P_SHM_ACCESS_READWRITE);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'b');
		BOOST_CHECK (p_shm_unlock (shm));
	}

	p_shm_free (shm);
	p_shm_free (shm2);
}

BOOST_AUTO_TEST_CASE (pshm_thread_test)
{
	PShm		*shm;
	PUThread	*thr1, *thr2, *thr3;
	ppointer	addr;
	pint		i, val;
	pboolean	test_ok;

	srand ((puint) time (NULL));

	shm = p_shm_new ("p_shm_test_memory_block_3", 1024 * 1024, P_SHM_ACCESS_READWRITE);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024 * 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	thr1 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr1 != NULL);

	thr2 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr2 != NULL);

	thr3 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr3 != NULL);

	BOOST_CHECK (p_uthread_join (thr1) == 0);
	BOOST_CHECK (p_uthread_join (thr2) == 0);
	BOOST_CHECK (p_uthread_join (thr3) == 0);

	test_ok = TRUE;
	val = *((pchar *) addr);

	for (i = 1; i < 1024 * 1024; ++i)
		if (*(((pchar *) addr) + i) != val) {
			test_ok = FALSE;
			break;
		}

	BOOST_REQUIRE (test_ok == TRUE);

	p_uthread_free (thr1);
	p_uthread_free (thr2);
	p_uthread_free (thr3);
	p_shm_free (shm);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include <QIcon>
#include <QSet>
#include <QDir>

#include <QDebug>

#include "themeiconsmodel.h"

ThemeIconsModel::ThemeIconsModel(QHash<QString, IconTheme> themes, const QString &theme_name,
                                 QObject *parent):
    QAbstractListModel(parent),
    icon_themes(std::move(themes))
{
    set_current_theme(theme_name.isNull() ? QIcon::themeName() : theme_name);
}

ThemeIconsModel::ThemeIconsModel(QObject *parent): QAbstractListModel(parent)
{

}

int ThemeIconsModel::rowCount(const QModelIndex &) const
{
    return icon_names.size();
}

QVariant ThemeIconsModel::data(const QModelIndex &index, int role) const
{
    const int row = index.row();
    if (row < 0 || row >= icon_names.size() || index.column() != 0) {
        return QVariant();
    }
    switch(role) {
        case Qt::DisplayRole:
        case Qt::StatusTipRole:
        case Qt::ToolTipRole:
            return icon_names.at(row);
        case Qt::DecorationRole: {
            const QString &name = icon_names.at(row);
            // TODO: implement cache with limited amount of memory
            // TODO: implement async loading
            if (icon_cache.contains(name))
                return icon_cache[name];
            QIcon icon = icon_by_name(name);
            icon_cache[name] = icon;
            return icon;
        }
        default:
            return QVariant();
    }
}

void ThemeIconsModel::set_themes(const QHash<QString, IconTheme> &themes, const QString &theme_name)
{
    icon_themes=themes;
    set_current_theme(theme_name.isNull() ? QIcon::themeName() : theme_name);
}

void ThemeIconsModel::set_current_theme(QString theme)
{
    if (!icon_themes.contains(theme) || theme == selected_theme)
        return;

    beginResetModel();
    selected_theme = theme;
    icon_cache.clear();
    // build list of icons from selected theme and parent themes
    QSet<QString> theme_icons;
    QStringList theme_chain{selected_theme};
    for (int i = 0; i < theme_chain.size(); i++) {
        const IconTheme &theme = icon_themes[theme_chain[i]];
        theme_chain.append(theme.parents());
        theme_icons.unite(QSet<QString>::fromList(theme.icons().keys()));
    }
    icon_names = theme_icons.toList();
    qDebug() << "selected_theme: " << selected_theme;
    endResetModel();
}

QIcon ThemeIconsModel::icon_by_name(const QString &name) const
{
    static const char * extensions[IconTheme::FileExtension::LENGTH] = {
        "png",
        "svg",
        "xpm"
    };

    QStringList theme_chain{selected_theme};
    for (int i = 0; i < theme_chain.size(); i++) {
        const IconTheme &theme = icon_themes[theme_chain[i]];
        theme_chain.append(theme.parents());
        if (!theme.icons().contains(name))
            continue;
        QIcon icon;
        const QVector<IconTheme::Directory> &dirs = theme.dirs();
        // load files
        for (const IconTheme::IconInfo& icon_info: theme.icons()[name]) {
            QString file_path = QString("%1/%2/%3.%4")
                    .arg(theme.path())
                    .arg(dirs[icon_info.first].path)
                    .arg(name)
                    .arg(extensions[icon_info.second]);
            icon.addFile(file_path);
        }
        return icon;
    }
    qDebug() << "Icon " << name << " not found";
    return QIcon();
}
<commit_msg>Added static asserts to make sure named constants are consistent with extensions<commit_after>#include <QIcon>
#include <QSet>
#include <QDir>

#include <QDebug>

#include "themeiconsmodel.h"

ThemeIconsModel::ThemeIconsModel(QHash<QString, IconTheme> themes, const QString &theme_name,
                                 QObject *parent):
    QAbstractListModel(parent),
    icon_themes(std::move(themes))
{
    set_current_theme(theme_name.isNull() ? QIcon::themeName() : theme_name);
}

ThemeIconsModel::ThemeIconsModel(QObject *parent): QAbstractListModel(parent)
{

}

int ThemeIconsModel::rowCount(const QModelIndex &) const
{
    return icon_names.size();
}

QVariant ThemeIconsModel::data(const QModelIndex &index, int role) const
{
    const int row = index.row();
    if (row < 0 || row >= icon_names.size() || index.column() != 0) {
        return QVariant();
    }
    switch(role) {
        case Qt::DisplayRole:
        case Qt::StatusTipRole:
        case Qt::ToolTipRole:
            return icon_names.at(row);
        case Qt::DecorationRole: {
            const QString &name = icon_names.at(row);
            // TODO: implement cache with limited amount of memory
            // TODO: implement async loading
            if (icon_cache.contains(name))
                return icon_cache[name];
            QIcon icon = icon_by_name(name);
            icon_cache[name] = icon;
            return icon;
        }
        default:
            return QVariant();
    }
}

void ThemeIconsModel::set_themes(const QHash<QString, IconTheme> &themes, const QString &theme_name)
{
    icon_themes=themes;
    set_current_theme(theme_name.isNull() ? QIcon::themeName() : theme_name);
}

void ThemeIconsModel::set_current_theme(QString theme)
{
    if (!icon_themes.contains(theme) || theme == selected_theme)
        return;

    beginResetModel();
    selected_theme = theme;
    icon_cache.clear();
    // build list of icons from selected theme and parent themes
    QSet<QString> theme_icons;
    QStringList theme_chain{selected_theme};
    for (int i = 0; i < theme_chain.size(); i++) {
        const IconTheme &theme = icon_themes[theme_chain[i]];
        theme_chain.append(theme.parents());
        theme_icons.unite(QSet<QString>::fromList(theme.icons().keys()));
    }
    icon_names = theme_icons.toList();
    qDebug() << "selected_theme: " << selected_theme;
    endResetModel();
}

QIcon ThemeIconsModel::icon_by_name(const QString &name) const
{
    static_assert(IconTheme::FileExtension::PNG == 0, "IconTheme::FileExtension::PNG != 0");
    static_assert(IconTheme::FileExtension::SVG == 1, "IconTheme::FileExtension::SVG != 1");
    static_assert(IconTheme::FileExtension::XPM == 2, "IconTheme::FileExtension::XPM != 2");
    static const char * extensions[IconTheme::FileExtension::LENGTH] = {
        "png",
        "svg",
        "xpm"
    };

    QStringList theme_chain{selected_theme};
    for (int i = 0; i < theme_chain.size(); i++) {
        const IconTheme &theme = icon_themes[theme_chain[i]];
        theme_chain.append(theme.parents());
        if (!theme.icons().contains(name))
            continue;
        QIcon icon;
        const QVector<IconTheme::Directory> &dirs = theme.dirs();
        // load files
        for (const IconTheme::IconInfo& icon_info: theme.icons()[name]) {
            QString file_path = QString("%1/%2/%3.%4")
                    .arg(theme.path())
                    .arg(dirs[icon_info.first].path)
                    .arg(name)
                    .arg(extensions[icon_info.second]);
            icon.addFile(file_path);
        }
        return icon;
    }
    qDebug() << "Icon " << name << " not found";
    return QIcon();
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2012-2014 Jun Wu <quark@zju.edu.cn>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////

#include "fs.h"
#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <dirent.h>
#include <fcntl.h>
#include <list>
#include <mntent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/file.h>

namespace fs = lrun::fs;
using std::string;

const char fs::PATH_SEPARATOR = '/';
const char * const fs::PROC_PATH = "/proc";
const char * const fs::MOUNTS_PATH = "/proc/mounts";
const char * const fs::TYPE_CGROUP = "cgroup";
const char * const fs::TYPE_TMPFS  = "tmpfs";

string fs::join(const string& dirname, const string& basename) {
  size_t dirname_len = dirname.length();
  size_t basename_len = basename.length();
  int offset = 0;

  if (dirname_len == 0) return basename;
  else if (dirname[dirname_len - 1] == PATH_SEPARATOR) offset++;
  if (basename_len == 0) return dirname;
  else if (basename[0] == PATH_SEPARATOR) offset++;

  switch (offset) {
    case 0:
      return dirname + PATH_SEPARATOR + basename;
    case 2:
      return dirname + basename.substr(1);
    case 1: default:
      return dirname + basename;
  }
}

bool fs::is_absolute(const string& path) {
    return path.length() > 0 && path.data()[0] == PATH_SEPARATOR;
}

string fs::expand(const string& path) {
    std::list<string> paths;
    size_t pos = string::npos, start = 0;
    for (;;) {
        pos = path.find(PATH_SEPARATOR, pos + 1);
        size_t length = (pos == string::npos ? string::npos : pos - start);
        if (length > 0) {
            string name = path.substr(start, length);
            if (name == "..") {
                if (paths.size() > 0) paths.pop_back();
            } else if (name == ".") {
                // ignored
            } else {
                paths.push_back(name);
            }
        }

        start = pos + 1;
        if (pos == string::npos) break;
    }

    string result;
    for (std::list<string>::iterator it = paths.begin(); it != paths.end(); ++it) {
        string name = *it;
        result += PATH_SEPARATOR;
        result += name;
    }
    if (fs::is_absolute(path)) {
        if (result.length() == 0) result = PATH_SEPARATOR;
    } else {
        if (result.length() > 0) result = result.substr(1);
    }
    return result;
}

string fs::resolve(const string& path, const string& work_dir) {
    string result = expand(is_absolute(path) ? path : join(work_dir, path));
    int dirfd = AT_FDCWD;
    size_t buf_size = PATH_MAX;
    char *buf = (char*) malloc(buf_size + 1);

    if (!buf) goto cleanup;

    if (!work_dir.empty() && !is_absolute(path)) {
        dirfd = open(work_dir.c_str(), O_RDONLY);
        if (dirfd == -1) goto cleanup;
    }

    for (string link = path;;) { // recursively readlink
        for (;;) {
            // readlink requires unknown space, try until we got full path
            ssize_t out_size = readlinkat(dirfd, link.c_str(), buf, buf_size);
            if (out_size < 0) {
                goto cleanup;
            } else if ((size_t) out_size >= buf_size) {
                // try bigger
                char *new_buf = (char*) realloc(buf, buf_size + PATH_MAX + 1);
                if (new_buf) {
                    buf = new_buf;
                    buf_size += PATH_MAX;
                } else {
                    // give up
                    result = buf;
                    break;
                }
            } else {
                buf[out_size] = 0;
                link = result = buf;
                break;
            }
        };
    }

cleanup:
    if (dirfd != -1 && dirfd != AT_FDCWD) close(dirfd);
    if (buf) free(buf);
    return result;
}

bool fs::is_accessible(const string& path, int mode, const string& work_dir) {
    int dirfd = AT_FDCWD;
    bool result = false;
    if (!work_dir.empty() && !is_absolute(path)) {
        dirfd = open(work_dir.c_str(), O_RDONLY);
        if (dirfd == -1) goto cleanup;
    }
    result = (faccessat(dirfd, path.c_str(), mode, 0) == 0);

cleanup:
    if (dirfd != -1 && dirfd != AT_FDCWD) close(dirfd);
    return result;
}

int fs::write(const string& path, const string& content) {
    FILE* fp = fopen(path.c_str(), "w");
    if (!fp) return -1;

    size_t wmb = fwrite(content.c_str(), content.size(), 1, fp);
    fclose(fp);

    return wmb ? 0 : -2;
}

string fs::read(const string& path, size_t max_length) {
    FILE* fp = fopen(path.c_str(), "r");
    if (!fp) return "";

    size_t buffer_size = max_length + 1;
    char buffer[buffer_size];

    int nread = fread(buffer, 1, buffer_size, fp);
    fclose(fp);

    buffer[max_length] = 0;
    if (nread >= 0 && (size_t)nread < max_length) buffer[nread] = 0;

    return buffer;
}

int fs::is_dir(const string& path) {
    struct stat buf;
    if (stat(path.c_str(), &buf) == -1) return 0;
    return S_ISDIR(buf.st_mode) ? 1 : 0;
}

int fs::mkdir_p(const string& dir, const mode_t mode) {
    // do nothing if directory exists
    if (is_dir(dir)) return 0;

    // make each dirs
    const char * head = dir.c_str();
    int nmkdir = 0;
    for (const char * p = head; *p; ++p) {
        if (*p == PATH_SEPARATOR && p > head) {
            int e = mkdir(dir.substr(0, p - head).c_str(), mode);
            if (e == 0) ++nmkdir;
        }
    }
    int e = mkdir(dir.c_str(), mode);

    if (e < 0 /* && errno != EEXIST */) return -1;
    return nmkdir;
}

int fs::rm_rf(const string& path) {
    // TODO use more efficient implement like coreutils/rm

    // try to remove single file or an empty dir
    if (unlink(path.c_str()) == 0) return 0;
    if (rmdir(path.c_str()) == 0) return 0;

    // try to list path contents
    struct dirent **namelist = 0;
    int nlist = scandir(path.c_str(), &namelist, 0, alphasort);

    for (int i = 0; i < nlist; ++i) {
        const char * name = namelist[i]->d_name;
        // skip . and ..
        if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) fs::rm_rf(join(path, name));
        free(namelist[i]);
    }

    if (namelist) free(namelist);

    // try remove empty dir again
    if (rmdir(path.c_str()) == 0) return 0;

    // otherwise something must went wrong
    return -1;
}

int fs::chmod(const std::string& path, const mode_t mode) {
    return ::chmod(path.c_str(), mode);
}

int fs::remount(const string& dest, unsigned long flags) {
    int e = mount(NULL, dest.c_str(), NULL, MS_REMOUNT | flags, NULL);
    return e;
}

int fs::mount_bind(const string& src, const string& dest) {
    int e = mount(src.c_str(),
                  dest.c_str(),
                  NULL,
                  MS_BIND | MS_NOSUID,
                  NULL);
    return e;
}

int fs::mount_tmpfs(const string& dest, size_t max_size, mode_t mode) {
    char tmpfs_opts[256];
    snprintf(tmpfs_opts, sizeof tmpfs_opts, "size=%lu,mode=0%o", (unsigned long)max_size, (unsigned int)mode);

    int e = mount(NULL,
                 dest.c_str(),
                 TYPE_TMPFS,
                 MS_NOSUID | MS_NODEV,
                 tmpfs_opts);
    return e;
}

int fs::mount_set_shared(const string& dest, int type) {
    return mount(NULL, dest.c_str(), NULL, type, NULL);
}

int fs::umount(const string& dest, bool lazy) {
    if (lazy) {
        return umount2(dest.c_str(), MNT_DETACH);
    } else {
        return umount(dest.c_str());
    }
}

std::map<string, fs::MountEntry> fs::get_mounts() {
    std::map<string, fs::MountEntry> result;
    FILE *fp = setmntent(fs::MOUNTS_PATH, "r");
    if (!fp) return result;

    for (struct mntent *ent; (ent = getmntent(fp));) {
        result[string(ent->mnt_dir)] = {
            /* .type = */ ent->mnt_type,
            /* .opts = */ ent->mnt_opts,
            /* .fsname = */ ent->mnt_fsname,
            /* .dir = */ ent->mnt_dir
        };
    }
    endmntent(fp);
    return result;
}

fs::ScopedFileLock::ScopedFileLock(const char path[]) {
    int fd = open(path, O_RDONLY);
    if (fd < 0) return;
    if (flock(fd, LOCK_EX) == 0) {
        this->fd_ = fd;
    } else {
        close(fd);
        this->fd_ = -1;
    }
}

fs::ScopedFileLock::~ScopedFileLock() {
    int fd = this->fd_;
    if (fd < 0) return;
    flock(fd, LOCK_UN);
    close(fd);
}

int fs::Tracer::init(unsigned int flags, unsigned int event_f_flags, fs::Tracer::tracer_cb callback) {
    cb_ = callback;
    fan_fd_ = fanotify_init(flags, event_f_flags);
    if (fan_fd_ < 0) goto failure;
    return 0;

failure:
    cb_ = NULL;
    fan_fd_ = -1;
    return -1;
}

fs::Tracer::Tracer(int fan_fd) : fan_fd_(fan_fd) {}

int fs::Tracer::mark(const char path[], unsigned int flags, uint64_t mask) {
    if (fan_fd_ < 0) return -1;
    return fanotify_mark(fan_fd_, flags, mask, /* dirfd */ 0, path);
}

void fs::Tracer::process_events() {
    if (fan_fd_ < 0) return;

    while (1) {
        char buf[4096];
        ssize_t len = ::read(fan_fd_, buf, sizeof(buf));
        if (len <= 0) return;

        struct fanotify_event_metadata *metadata = (struct fanotify_event_metadata*) buf;
        while (FAN_EVENT_OK(metadata, len)) {
            assert(metadata->vers >= 2);

            int cb_ret = 0;
            if (cb_) {
                // FIXME: longer path is not supported
                char path[4096];
                path[0] = '\0';
                if (metadata->fd >= 0) {
                    sprintf(path, "/proc/self/fd/%d", metadata->fd);
                    ssize_t path_len = readlink(path, path, sizeof(path) - 1);
                    if (path_len >= 0) path[path_len] = '\0';
                }
                cb_ret = cb_(path, metadata->fd, metadata->pid, metadata->mask);
            }

            if (metadata->mask & FAN_ALL_PERM_EVENTS) {
                struct fanotify_response response;
                response.fd = metadata->fd;
                response.response = cb_ret == 0 ? FAN_ALLOW : FAN_DENY;
                int ret = ::write(fan_fd_, &response, sizeof(response));
                (void)ret;
            }

            metadata = FAN_EVENT_NEXT(metadata, len);
        }
    }
}

int fs::Tracer::get_fan_fd() const {
    return fan_fd_;
}

fs::Tracer::~Tracer() {
    if (fan_fd_ >= 0) close(fan_fd_);
}

fs::PathNode::PathNode() {
    flag_ = 0;
}

fs::PathNode::~PathNode() {
    for (std::map<char, fs::PathNode*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it) {
        if (it->second != NULL) {
            if (it->second != this) delete it->second;
            it->second = NULL;
        }
    }
}

fs::PathNode* fs::PathNode::walk(const char *p, int ttl) {
    if (ttl == 0) return this;

    fs::PathNode *next;
    if (children_.count(*p) == 0) {
        next = children_[*p] = new fs::PathNode();
    } else {
        next = children_[*p];
    }
    return next->walk(p + 1, ttl - 1);
}

void fs::PathNode::set(const char path[], int flag, int wildcard) {
    int ttl = strlen(path);
    if (!wildcard) ttl += 1;  // including the last char ('\0')
    walk(path, ttl)->flag_ = flag;
}

int fs::PathNode::get(const char path[]) {
    const char *p = &path[0];
    const char *p_end = path + strlen(path) + 1;
    int flag = 0;

    for (fs::PathNode *current = this; current;) {
        if (current->flag_) flag = current->flag_;
        if (p == p_end) break;  // just processed the last char, '\0'
        __typeof(current->children_.begin()) it = current->children_.find(*p++);
        if (it == current->children_.end()) current = NULL; else current = it->second;
    }
    return flag;
}
<commit_msg>Implement fs::get_mount_point<commit_after>////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2012-2014 Jun Wu <quark@zju.edu.cn>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////

#include "fs.h"
#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <dirent.h>
#include <fcntl.h>
#include <list>
#include <mntent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/file.h>

namespace fs = lrun::fs;
using std::string;

const char fs::PATH_SEPARATOR = '/';
const char * const fs::PROC_PATH = "/proc";
const char * const fs::MOUNTS_PATH = "/proc/mounts";
const char * const fs::TYPE_CGROUP = "cgroup";
const char * const fs::TYPE_TMPFS  = "tmpfs";

string fs::join(const string& dirname, const string& basename) {
  size_t dirname_len = dirname.length();
  size_t basename_len = basename.length();
  int offset = 0;

  if (dirname_len == 0) return basename;
  else if (dirname[dirname_len - 1] == PATH_SEPARATOR) offset++;
  if (basename_len == 0) return dirname;
  else if (basename[0] == PATH_SEPARATOR) offset++;

  switch (offset) {
    case 0:
      return dirname + PATH_SEPARATOR + basename;
    case 2:
      return dirname + basename.substr(1);
    case 1: default:
      return dirname + basename;
  }
}

bool fs::is_absolute(const string& path) {
    return path.length() > 0 && path.data()[0] == PATH_SEPARATOR;
}

string fs::expand(const string& path) {
    std::list<string> paths;
    size_t pos = string::npos, start = 0;
    for (;;) {
        pos = path.find(PATH_SEPARATOR, pos + 1);
        size_t length = (pos == string::npos ? string::npos : pos - start);
        if (length > 0) {
            string name = path.substr(start, length);
            if (name == "..") {
                if (paths.size() > 0) paths.pop_back();
            } else if (name == ".") {
                // ignored
            } else {
                paths.push_back(name);
            }
        }

        start = pos + 1;
        if (pos == string::npos) break;
    }

    string result;
    for (std::list<string>::iterator it = paths.begin(); it != paths.end(); ++it) {
        string name = *it;
        result += PATH_SEPARATOR;
        result += name;
    }
    if (fs::is_absolute(path)) {
        if (result.length() == 0) result = PATH_SEPARATOR;
    } else {
        if (result.length() > 0) result = result.substr(1);
    }
    return result;
}

string fs::resolve(const string& path, const string& work_dir) {
    string result = expand(is_absolute(path) ? path : join(work_dir, path));
    int dirfd = AT_FDCWD;
    size_t buf_size = PATH_MAX;
    char *buf = (char*) malloc(buf_size + 1);

    if (!buf) goto cleanup;

    if (!work_dir.empty() && !is_absolute(path)) {
        dirfd = open(work_dir.c_str(), O_RDONLY);
        if (dirfd == -1) goto cleanup;
    }

    for (string link = path;;) { // recursively readlink
        for (;;) {
            // readlink requires unknown space, try until we got full path
            ssize_t out_size = readlinkat(dirfd, link.c_str(), buf, buf_size);
            if (out_size < 0) {
                goto cleanup;
            } else if ((size_t) out_size >= buf_size) {
                // try bigger
                char *new_buf = (char*) realloc(buf, buf_size + PATH_MAX + 1);
                if (new_buf) {
                    buf = new_buf;
                    buf_size += PATH_MAX;
                } else {
                    // give up
                    result = buf;
                    break;
                }
            } else {
                buf[out_size] = 0;
                link = result = buf;
                break;
            }
        };
    }

cleanup:
    if (dirfd != -1 && dirfd != AT_FDCWD) close(dirfd);
    if (buf) free(buf);
    return result;
}

bool fs::is_accessible(const string& path, int mode, const string& work_dir) {
    int dirfd = AT_FDCWD;
    bool result = false;
    if (!work_dir.empty() && !is_absolute(path)) {
        dirfd = open(work_dir.c_str(), O_RDONLY);
        if (dirfd == -1) goto cleanup;
    }
    result = (faccessat(dirfd, path.c_str(), mode, 0) == 0);

cleanup:
    if (dirfd != -1 && dirfd != AT_FDCWD) close(dirfd);
    return result;
}

int fs::write(const string& path, const string& content) {
    FILE* fp = fopen(path.c_str(), "w");
    if (!fp) return -1;

    size_t wmb = fwrite(content.c_str(), content.size(), 1, fp);
    fclose(fp);

    return wmb ? 0 : -2;
}

string fs::read(const string& path, size_t max_length) {
    FILE* fp = fopen(path.c_str(), "r");
    if (!fp) return "";

    size_t buffer_size = max_length + 1;
    char buffer[buffer_size];

    int nread = fread(buffer, 1, buffer_size, fp);
    fclose(fp);

    buffer[max_length] = 0;
    if (nread >= 0 && (size_t)nread < max_length) buffer[nread] = 0;

    return buffer;
}

int fs::is_dir(const string& path) {
    struct stat buf;
    if (stat(path.c_str(), &buf) == -1) return 0;
    return S_ISDIR(buf.st_mode) ? 1 : 0;
}

int fs::mkdir_p(const string& dir, const mode_t mode) {
    // do nothing if directory exists
    if (is_dir(dir)) return 0;

    // make each dirs
    const char * head = dir.c_str();
    int nmkdir = 0;
    for (const char * p = head; *p; ++p) {
        if (*p == PATH_SEPARATOR && p > head) {
            int e = mkdir(dir.substr(0, p - head).c_str(), mode);
            if (e == 0) ++nmkdir;
        }
    }
    int e = mkdir(dir.c_str(), mode);

    if (e < 0 /* && errno != EEXIST */) return -1;
    return nmkdir;
}

int fs::rm_rf(const string& path) {
    // TODO use more efficient implement like coreutils/rm

    // try to remove single file or an empty dir
    if (unlink(path.c_str()) == 0) return 0;
    if (rmdir(path.c_str()) == 0) return 0;

    // try to list path contents
    struct dirent **namelist = 0;
    int nlist = scandir(path.c_str(), &namelist, 0, alphasort);

    for (int i = 0; i < nlist; ++i) {
        const char * name = namelist[i]->d_name;
        // skip . and ..
        if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) fs::rm_rf(join(path, name));
        free(namelist[i]);
    }

    if (namelist) free(namelist);

    // try remove empty dir again
    if (rmdir(path.c_str()) == 0) return 0;

    // otherwise something must went wrong
    return -1;
}

int fs::chmod(const std::string& path, const mode_t mode) {
    return ::chmod(path.c_str(), mode);
}

int fs::remount(const string& dest, unsigned long flags) {
    int e = mount(NULL, dest.c_str(), NULL, MS_REMOUNT | flags, NULL);
    return e;
}

int fs::mount_bind(const string& src, const string& dest) {
    int e = mount(src.c_str(),
                  dest.c_str(),
                  NULL,
                  MS_BIND | MS_NOSUID,
                  NULL);
    return e;
}

int fs::mount_tmpfs(const string& dest, size_t max_size, mode_t mode) {
    char tmpfs_opts[256];
    snprintf(tmpfs_opts, sizeof tmpfs_opts, "size=%lu,mode=0%o", (unsigned long)max_size, (unsigned int)mode);

    int e = mount(NULL,
                 dest.c_str(),
                 TYPE_TMPFS,
                 MS_NOSUID | MS_NODEV,
                 tmpfs_opts);
    return e;
}

int fs::mount_set_shared(const string& dest, int type) {
    return mount(NULL, dest.c_str(), NULL, type, NULL);
}

int fs::umount(const string& dest, bool lazy) {
    if (lazy) {
        return umount2(dest.c_str(), MNT_DETACH);
    } else {
        return umount(dest.c_str());
    }
}

std::map<string, fs::MountEntry> fs::get_mounts() {
    std::map<string, fs::MountEntry> result;
    FILE *fp = setmntent(fs::MOUNTS_PATH, "r");
    if (!fp) return result;

    for (struct mntent *ent; (ent = getmntent(fp));) {
        result[string(ent->mnt_dir)] = {
            /* .type = */ ent->mnt_type,
            /* .opts = */ ent->mnt_opts,
            /* .fsname = */ ent->mnt_fsname,
            /* .dir = */ ent->mnt_dir
        };
    }
    endmntent(fp);
    return result;
}

std::string get_mount_point(const std::string& path) {
  string result = "/";
  static std::map<string, fs::MountEntry> mounts;
  if (mounts.empty()) mounts = fs::get_mounts();

  for (__typeof(mounts.begin()) it = mounts.begin(); it != mounts.end(); ++it) {
    if (it->second.type == "lofs") continue;
    if (it->first.length() > result.length() && path.substr(0, it->first.length()) == it->first) {
      result = it->first;
    }
  }

  return result;
}

fs::ScopedFileLock::ScopedFileLock(const char path[]) {
    int fd = open(path, O_RDONLY);
    if (fd < 0) return;
    if (flock(fd, LOCK_EX) == 0) {
        this->fd_ = fd;
    } else {
        close(fd);
        this->fd_ = -1;
    }
}

fs::ScopedFileLock::~ScopedFileLock() {
    int fd = this->fd_;
    if (fd < 0) return;
    flock(fd, LOCK_UN);
    close(fd);
}

int fs::Tracer::init(unsigned int flags, unsigned int event_f_flags, fs::Tracer::tracer_cb callback) {
    cb_ = callback;
    fan_fd_ = fanotify_init(flags, event_f_flags);
    if (fan_fd_ < 0) goto failure;
    return 0;

failure:
    cb_ = NULL;
    fan_fd_ = -1;
    return -1;
}

fs::Tracer::Tracer(int fan_fd) : fan_fd_(fan_fd) {}

int fs::Tracer::mark(const char path[], unsigned int flags, uint64_t mask) {
    if (fan_fd_ < 0) return -1;
    return fanotify_mark(fan_fd_, flags, mask, /* dirfd */ 0, path);
}

void fs::Tracer::process_events() {
    if (fan_fd_ < 0) return;

    while (1) {
        char buf[4096];
        ssize_t len = ::read(fan_fd_, buf, sizeof(buf));
        if (len <= 0) return;

        struct fanotify_event_metadata *metadata = (struct fanotify_event_metadata*) buf;
        while (FAN_EVENT_OK(metadata, len)) {
            assert(metadata->vers >= 2);

            int cb_ret = 0;
            if (cb_) {
                // FIXME: longer path is not supported
                char path[4096];
                path[0] = '\0';
                if (metadata->fd >= 0) {
                    sprintf(path, "/proc/self/fd/%d", metadata->fd);
                    ssize_t path_len = readlink(path, path, sizeof(path) - 1);
                    if (path_len >= 0) path[path_len] = '\0';
                }
                cb_ret = cb_(path, metadata->fd, metadata->pid, metadata->mask);
            }

            if (metadata->mask & FAN_ALL_PERM_EVENTS) {
                struct fanotify_response response;
                response.fd = metadata->fd;
                response.response = cb_ret == 0 ? FAN_ALLOW : FAN_DENY;
                int ret = ::write(fan_fd_, &response, sizeof(response));
                (void)ret;
            }

            metadata = FAN_EVENT_NEXT(metadata, len);
        }
    }
}

int fs::Tracer::get_fan_fd() const {
    return fan_fd_;
}

fs::Tracer::~Tracer() {
    if (fan_fd_ >= 0) close(fan_fd_);
}

fs::PathNode::PathNode() {
    flag_ = 0;
}

fs::PathNode::~PathNode() {
    for (std::map<char, fs::PathNode*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it) {
        if (it->second != NULL) {
            if (it->second != this) delete it->second;
            it->second = NULL;
        }
    }
}

fs::PathNode* fs::PathNode::walk(const char *p, int ttl) {
    if (ttl == 0) return this;

    fs::PathNode *next;
    if (children_.count(*p) == 0) {
        next = children_[*p] = new fs::PathNode();
    } else {
        next = children_[*p];
    }
    return next->walk(p + 1, ttl - 1);
}

void fs::PathNode::set(const char path[], int flag, int wildcard) {
    int ttl = strlen(path);
    if (!wildcard) ttl += 1;  // including the last char ('\0')
    walk(path, ttl)->flag_ = flag;
}

int fs::PathNode::get(const char path[]) {
    const char *p = &path[0];
    const char *p_end = path + strlen(path) + 1;
    int flag = 0;

    for (fs::PathNode *current = this; current;) {
        if (current->flag_) flag = current->flag_;
        if (p == p_end) break;  // just processed the last char, '\0'
        __typeof(current->children_.begin()) it = current->children_.find(*p++);
        if (it == current->children_.end()) current = NULL; else current = it->second;
    }
    return flag;
}
<|endoftext|>


<commit_before>#pragma once

#include <array>
#include <cassert>
#include <cstdint>
#include <iostream>

// TODO: Try dedicated u16 for each cell #performance

class State
{
private:
    using u8 = std::uint8_t;
    using u16 = std::uint16_t;

    std::array<u8, 92> mBytes;

public:
    State()
    {
        // Set all flags to true
        for (auto& b : mBytes)
        {
            b = 255;
        }
    }

    u16 GetCell(u16 cellNo) const
    {
        u16 skipBits = cellNo * u16(9);
        u8 skipBytes = skipBits / u16(8);

        u16 state = (mBytes[skipBytes] << u16(8)) + mBytes[skipBytes + u8(1)];

        u8 shiftBits = u16(7) - (skipBits - skipBytes * u16(8));

        state = (state & (u16(511) << shiftBits)) >> shiftBits;

        return state;
    }

    void SetCell(u16 cellNo, u16 state)
    {
        u16 skipBits = cellNo * u16(9);
        u8 skipBytes = skipBits / u16(8);

        u8& byte1 = mBytes[skipBytes];
        u8& byte2 = mBytes[skipBytes + u8(1)];

        u8 shiftBits = u16(7) - (skipBits - skipBytes * u16(8));
        state = state << shiftBits;

        u16 mask = ~(u16(511) << shiftBits);

        byte1 = byte1 & (mask >> u16(8));
        byte1 = byte1 | (state >> u16(8));

        byte2 = byte2 & ((mask << u16(8)) >> u16(8));
        byte2 = byte2 | ((state << u16(8)) >> u16(8));
    }

    u8 PickNonFinalisedCell()
    {
        u8 bestCellNo = 255;
        u8 bestPossibilities = 255;

        for (u8 i = 0u; i != 81u; ++i)
        {
            u16 cell = GetCell(i);
            u8 possibilities = NumPossibilities(cell);

            // Shortcut: can't do better than 2
            if (possibilities == u8(2))
            {
                return i;
            }

            if (possibilities > u8(1) && possibilities < bestPossibilities)
            {
                bestCellNo = i;
                bestPossibilities = possibilities;
            }
        }

        return bestCellNo;
    }

    // TODO: there are other ways to do this, investigate their #performance
    static u8 NumPossibilities(u16 cell)
    {
        return __builtin_popcount(cell);
    }

    static u8 CellToNum(u16 cell)
    {
        if (cell == 0 || (cell & (cell - u16(1))) != 0)
        {
            return 0;
        }

        u8 n = 9;
        u16 nn = 1;

        while (nn != cell)
        {
            nn <<= 1;
            --n;
        }

        return n;
    }

    static u16 NumToCell(u8 n)
    {
        if (u8(1) <= n && n <= u8(9))
        {
            --n;
            return u16(1) << (u8(8) - n);
        }

        assert(n == 0);

        return 511;
    }

    friend std::ostream& operator<<(std::ostream& os, const State& state)
    {
        for (u8 i = 0u; i != 81u; ++i)
        {
            os << int(State::CellToNum(state.GetCell(i)));
        }

        return os;
    }

    friend std::istream& operator>>(std::istream& is, State& state)
    {
        for (u8 i = 0u; i != 81u; ++i)
        {
            u8 n;
            is >> n;
            assert(u8('0') <= n && n <= u8('9'));
            state.SetCell(i, State::NumToCell(n - u8('0')));
        }

        return is;
    }
};
<commit_msg>Storing a uint16_t per cell is >2x faster<commit_after>#pragma once

#include <array>
#include <cassert>
#include <cstdint>
#include <iostream>

// TODO: Try dedicated u16 for each cell #performance

class State
{
private:
    using u8 = std::uint8_t;
    using u16 = std::uint16_t;

    std::array<u16, 81> mCells;

public:
    State()
    {
        // Set all flags to true
        for (auto& c : mCells)
        {
            c = 511;
        }
    }

    u16 GetCell(u16 cellNo) const
    {
        return mCells[cellNo];
    }

    void SetCell(u16 cellNo, u16 state)
    {
        mCells[cellNo] = state;
    }

    u8 PickNonFinalisedCell()
    {
        u8 bestCellNo = 255;
        u8 bestPossibilities = 255;

        for (u8 i = 0u; i != 81u; ++i)
        {
            u16 cell = GetCell(i);
            u8 possibilities = NumPossibilities(cell);

            // Shortcut: can't do better than 2
            if (possibilities == u8(2))
            {
                return i;
            }

            if (possibilities > u8(1) && possibilities < bestPossibilities)
            {
                bestCellNo = i;
                bestPossibilities = possibilities;
            }
        }

        return bestCellNo;
    }

    // TODO: there are other ways to do this, investigate their #performance
    static u8 NumPossibilities(u16 cell)
    {
        return __builtin_popcount(cell);
    }

    static u8 CellToNum(u16 cell)
    {
        if (cell == 0 || (cell & (cell - u16(1))) != 0)
        {
            return 0;
        }

        u8 n = 9;
        u16 nn = 1;

        while (nn != cell)
        {
            nn <<= 1;
            --n;
        }

        return n;
    }

    static u16 NumToCell(u8 n)
    {
        if (u8(1) <= n && n <= u8(9))
        {
            --n;
            return u16(1) << (u8(8) - n);
        }

        assert(n == 0);

        return 511;
    }

    friend std::ostream& operator<<(std::ostream& os, const State& state)
    {
        for (u8 i = 0u; i != 81u; ++i)
        {
            os << int(State::CellToNum(state.GetCell(i)));
        }

        return os;
    }

    friend std::istream& operator>>(std::istream& is, State& state)
    {
        for (u8 i = 0u; i != 81u; ++i)
        {
            u8 n;
            is >> n;
            assert(u8('0') <= n && n <= u8('9'));
            state.SetCell(i, State::NumToCell(n - u8('0')));
        }

        return is;
    }
};
<|endoftext|>


<commit_before>/*
 * Copyright 2020 Benoy Bose
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef HOOLANG_UTILITY_HH
#define HOOLANG_UTILITY_HH

#include <cstdint>
#include <vector>
#include <string>
#include <cstdint>
#include <list>

#define UTILITY_OFFSET8 8
#define UTILITY_OFFSET16 16
#define UTILITY_OFFSET24 24

namespace hoo
{
    namespace common
    {
        class Utility
        {
        public:
            static std::vector<std::uint8_t> GetBytes(std::uint64_t value);

            template <typename T>
            static void AppendTo(std::vector<T> &to, const std::vector<T> &from)
            {
                to.insert(to.end(), from.begin(), from.end());
            }

            static std::string ToHex(std::uint8_t byte);

            static constexpr std::uint64_t EncodeToUInt64(std::uint8_t b0, std::uint8_t b1)
            {
                std::uint64_t v0 = b0;
                std::uint64_t v1 = (uint64_t)b1 << (uint8_t)UTILITY_OFFSET8;
                return v1 | v0;
            }

            static constexpr std::uint64_t EncodeToUInt64(std::uint8_t b0, std::uint8_t b1, std::uint8_t b2)
            {
                std::uint64_t v0 = b0;
                std::uint64_t v1 = (uint64_t)b1 << (uint8_t)UTILITY_OFFSET8;
                std::uint64_t v2 = (uint64_t)b2 << (uint8_t)UTILITY_OFFSET16;
                return v2 | v1 | v0;
            }

            static constexpr std::uint64_t EncodeToUInt64(std::uint8_t b0, std::uint8_t b1,
                                                          std::uint8_t b2, std::uint8_t b3)
            {
                std::uint64_t v0 = b0;
                std::uint64_t v1 = (uint64_t)b1 << (uint8_t)UTILITY_OFFSET8;
                std::uint64_t v2 = (uint64_t)b2 << (uint8_t)UTILITY_OFFSET16;
                std::uint64_t v3 = (uint64_t)b3 << (uint8_t)UTILITY_OFFSET24;
                return v3 | v2 | v1 | v0;
            }

            template <typename T>
            T First(std::list<T> items)
            {
                if (0 == items.size())
                {
                    throw std::runtime_error("List is empty");
                }

                return * items.begin();
            }

            template <typename T>
            T Last(std::list<T> items)
            {
                if (0 == items.size())
                {
                    throw std::runtime_error("List is empty");
                }
                auto item = * (items.end() --);
                return item;
            }
        };
    } // namespace common
} // namespace hoo
#endif //HOOLANG_UTILITY_HH
<commit_msg>Included standard header stdexcept<commit_after>/*
 * Copyright 2020 Benoy Bose
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef HOOLANG_UTILITY_HH
#define HOOLANG_UTILITY_HH

#include <cstdint>
#include <vector>
#include <string>
#include <cstdint>
#include <list>
#include <stdexcept>

#define UTILITY_OFFSET8 8
#define UTILITY_OFFSET16 16
#define UTILITY_OFFSET24 24

namespace hoo
{
    namespace common
    {
        class Utility
        {
        public:
            static std::vector<std::uint8_t> GetBytes(std::uint64_t value);

            template <typename T>
            static void AppendTo(std::vector<T> &to, const std::vector<T> &from)
            {
                to.insert(to.end(), from.begin(), from.end());
            }

            static std::string ToHex(std::uint8_t byte);

            static constexpr std::uint64_t EncodeToUInt64(std::uint8_t b0, std::uint8_t b1)
            {
                std::uint64_t v0 = b0;
                std::uint64_t v1 = (uint64_t)b1 << (uint8_t)UTILITY_OFFSET8;
                return v1 | v0;
            }

            static constexpr std::uint64_t EncodeToUInt64(std::uint8_t b0, std::uint8_t b1, std::uint8_t b2)
            {
                std::uint64_t v0 = b0;
                std::uint64_t v1 = (uint64_t)b1 << (uint8_t)UTILITY_OFFSET8;
                std::uint64_t v2 = (uint64_t)b2 << (uint8_t)UTILITY_OFFSET16;
                return v2 | v1 | v0;
            }

            static constexpr std::uint64_t EncodeToUInt64(std::uint8_t b0, std::uint8_t b1,
                                                          std::uint8_t b2, std::uint8_t b3)
            {
                std::uint64_t v0 = b0;
                std::uint64_t v1 = (uint64_t)b1 << (uint8_t)UTILITY_OFFSET8;
                std::uint64_t v2 = (uint64_t)b2 << (uint8_t)UTILITY_OFFSET16;
                std::uint64_t v3 = (uint64_t)b3 << (uint8_t)UTILITY_OFFSET24;
                return v3 | v2 | v1 | v0;
            }

            template <typename T>
            T First(std::list<T> items)
            {
                if (0 == items.size())
                {
                    throw std::runtime_error("List is empty");
                }

                return * items.begin();
            }

            template <typename T>
            T Last(std::list<T> items)
            {
                if (0 == items.size())
                {
                    throw std::runtime_error("List is empty");
                }
                auto item = * (items.end() --);
                return item;
            }
        };
    } // namespace common
} // namespace hoo
#endif //HOOLANG_UTILITY_HH
<|endoftext|>


<commit_before>// msdelay.cpp -- sit in a loop for a certain amount of time.

// https://github.com/isc1/wandurr
// this is a demonstrator program for the use of time in the wandurr1.cpp game
// mainly used to delay creature actions in the game world.

// For time, we use time.h/unistd.h clock_gettime(). see:
// http://en.cppreference.com/w/c/chrono/clock
// ...if you are getting weird time problems at 2147 seconds (or some multiple thereof)
// it's an int (or 32-bit) overflow problem. Use longs.

// for a nice discussion of time in c, see:
// http://www.catb.org/esr/time-programming/

// this code is based on the commentary at:
// https://blog.habets.se/2010/09/gettimeofday-should-never-be-used-to-measure-time.html

/* nice discussion of history of int, long, etc., excerpted below:
// http://stackoverflow.com/a/32924794
   "In brief, you shouldn’t make assumptions about what int and long mean beyond that int
   is at least 16 bits wide and fast, and long is at least 32 bits wide. For general
   purposes, use int. If you need an array index, use size_t or ptrdiff_t. If you want
   to be sure you can hold a number over 32,767, and seriously expect you might need to
   run on some 16-bit machine someday, use long or the fast type from <inttypes.h>.
   If you’re making a system call, use the same type as its arguments. If you’re storing
   a pointer in an integer type, use uintptr_t. If you need a number at least 64 bits
   wide, use long long, and if you know exactly the width you need, use the exact-width
   type."
*/

// c includes
#include <time.h>
#include <stdio.h>
#include <math.h>
// docs say clock_gettime() lives in time.h, but I get compiler errors unless
// I inlude unistd.h
#include <unistd.h>

// c++ includes
#include <iostream>
using namespace std;

// types & variables
typedef struct
{
    timespec    now;
    timespec    future;
} waitertype;

waitertype waiter;

// functions
unsigned long convmstotimespec(int millisecs)
{
    int secs;
    unsigned long nanosecs;
    timespec now;

    clock_gettime(CLOCK_MONOTONIC, &now);
    secs = trunc(millisecs/1000);
    nanosecs = (millisecs*1000000)-(secs*1000000000);
    return(nanosecs);
}

void schedulefuturetimespec(long delayms, timespec * futuretime)
{
    //long secs;
    unsigned long secs, nanosecs;
    timespec now;

    clock_gettime(CLOCK_MONOTONIC, &now);
    secs = trunc(delayms/1000);
    nanosecs = (delayms*1000000)-(secs*1000000000);
    futuretime->tv_sec = now.tv_sec + secs;
    futuretime->tv_nsec = now.tv_nsec + nanosecs;
}

int main()
{
    bool bail=false;
    long delayms=2112;
    timespec currenttime;

    // check the time and set a future time to quit
    //cout << "\nThis program uses clock_gettime() to wait " << delayms << " milliseconds.\n\n";
    clock_gettime(CLOCK_MONOTONIC, &waiter.now);
    schedulefuturetimespec(2112, &waiter.future);
    cout << "\nThis program uses clock_gettime() to wait " << delayms << " milliseconds.\n\n";
    printf("main(): Start time:                waiter.now.tv_sec:    %ld  waiter.now.tv_nsec:    %ld\n"
           , waiter.now.tv_sec, waiter.now.tv_nsec);
    printf("main(): Scheduled completion time: waiter.future.tv_sec: %ld  waiter.future.tv_nsec: %ld\n"
           , waiter.future.tv_sec, waiter.future.tv_nsec);

    // sit in the loop unti the time to quit comes to pass
    clock_gettime(CLOCK_MONOTONIC, &currenttime);
    while(!bail)
    {
        clock_gettime(CLOCK_MONOTONIC, &currenttime);
        // bail if we passed the seconds part AND the nanoseconds part
        if(currenttime.tv_sec == waiter.future.tv_sec)
            if(currenttime.tv_nsec >= waiter.future.tv_nsec)
                    bail=true;
        // also bail if we blew passed the seconds part entirely
        // (we don't care about the nanoseconds part at this point)
        if(currenttime.tv_sec > waiter.future.tv_sec)
            bail=true;
    }

    // print out the actual time we quit
    clock_gettime(CLOCK_MONOTONIC, &waiter.now);
    printf("main(): Actual completion time:    waiter.now.tv_sec:    %ld  waiter.now.tv_nsec:    %ld\n"
           , waiter.now.tv_sec, waiter.now.tv_nsec);
    cout << "DONE!\n\n";
}
<commit_msg>minor edits to comments<commit_after>// msdelay.cpp -- sit in a loop for a certain amount of time.

// https://github.com/isc1/wandurr
// this is a demonstrator program for the use of time in the wandurr1.cpp game
// mainly used to delay creature actions in the game world.

// For time, we use time.h/unistd.h clock_gettime(). see:
// http://en.cppreference.com/w/c/chrono/clock
// ...if you are getting weird time problems at 2147 seconds (or some multiple thereof)
// it's an int (or 32-bit) overflow problem. Use longs.

// for a nice discussion of time in c, see:
// http://www.catb.org/esr/time-programming/

// this code is based on the commentary at:
// https://blog.habets.se/2010/09/gettimeofday-should-never-be-used-to-measure-time.html

/* nice discussion of history of int, long, etc., excerpted below:
// http://stackoverflow.com/a/32924794
   "In brief, you shouldn’t make assumptions about what int and long mean beyond that int
   is at least 16 bits wide and fast, and long is at least 32 bits wide. For general
   purposes, use int. If you need an array index, use size_t or ptrdiff_t. If you want
   to be sure you can hold a number over 32,767, and seriously expect you might need to
   run on some 16-bit machine someday, use long or the fast type from <inttypes.h>.
   If you’re making a system call, use the same type as its arguments. If you’re storing
   a pointer in an integer type, use uintptr_t. If you need a number at least 64 bits
   wide, use long long, and if you know exactly the width you need, use the exact-width
   type."
*/

// c includes
#include <time.h>
#include <stdio.h>
#include <math.h>
// docs say clock_gettime() lives in time.h, but I get compiler errors unless
// I inlude unistd.h
#include <unistd.h>

// c++ includes
#include <iostream>
using namespace std;

// types & variables
typedef struct
{
    timespec    now;
    timespec    future;
} waitertype;

waitertype waiter;

// functions
unsigned long convmstotimespec(int millisecs)
{
    int secs;
    unsigned long nanosecs;
    timespec now;

    clock_gettime(CLOCK_MONOTONIC, &now);
    secs = trunc(millisecs/1000);
    nanosecs = (millisecs*1000000)-(secs*1000000000);
    return(nanosecs);
}

void schedulefuturetimespec(long delayms, timespec * futuretime)
{
    //long secs;
    unsigned long secs, nanosecs;
    timespec now;

    clock_gettime(CLOCK_MONOTONIC, &now);
    secs = trunc(delayms/1000);
    nanosecs = (delayms*1000000)-(secs*1000000000);
    futuretime->tv_sec = now.tv_sec + secs;
    futuretime->tv_nsec = now.tv_nsec + nanosecs;
}

int main()
{
    bool bail=false;
    long delayms=2112;
    timespec currenttime;

    // check the time and set a future time to quit
    clock_gettime(CLOCK_MONOTONIC, &waiter.now);
    schedulefuturetimespec(2112, &waiter.future);
    cout << "\nThis program uses clock_gettime() to wait " << delayms << " milliseconds.\n\n";
    printf("main(): Start time:                waiter.now.tv_sec:    %ld  waiter.now.tv_nsec:    %ld\n"
           , waiter.now.tv_sec, waiter.now.tv_nsec);
    printf("main(): Scheduled completion time: waiter.future.tv_sec: %ld  waiter.future.tv_nsec: %ld\n"
           , waiter.future.tv_sec, waiter.future.tv_nsec);

    // sit in the loop until the time to quit comes to pass
    clock_gettime(CLOCK_MONOTONIC, &currenttime);
    while(!bail)
    {
        clock_gettime(CLOCK_MONOTONIC, &currenttime);
        // bail if we passed the seconds part AND the nanoseconds part
        if(currenttime.tv_sec == waiter.future.tv_sec)
            if(currenttime.tv_nsec >= waiter.future.tv_nsec)
                    bail=true;
        // also bail if we blew passed the seconds part entirely
        // (we don't care about the nanoseconds part at this point)
        if(currenttime.tv_sec > waiter.future.tv_sec)
            bail=true;
    }

    // print out the actual time we quit
    clock_gettime(CLOCK_MONOTONIC, &waiter.now);
    printf("main(): Actual completion time:    waiter.now.tv_sec:    %ld  waiter.now.tv_nsec:    %ld\n"
           , waiter.now.tv_sec, waiter.now.tv_nsec);
    cout << "DONE!\n\n";
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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.

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 HOLDER 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.

*/

#include "SearchEngineData.h"

void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) {
    if(!forwardHeap.get()) {
        forwardHeap.reset(new QueryHeap(number_of_nodes));
    } else {
        forwardHeap->Clear();
    }
    if(!backwardHeap.get()) {
        backwardHeap.reset(new QueryHeap(number_of_nodes));
    } else {
        backwardHeap->Clear();
    }
}

void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) {
    if(!forwardHeap2.get()) {
        forwardHeap2.reset(new QueryHeap(number_of_nodes));
    } else {
        forwardHeap2->Clear();
    }
    if(!backwardHeap2.get()) {
        backwardHeap2.reset(new QueryHeap(number_of_nodes));
     } else {
        backwardHeap2->Clear();
    }
}

void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) {
    if(!forwardHeap3.get()) {
        forwardHeap3.reset(new QueryHeap(number_of_nodes));
    } else {
        forwardHeap3->Clear();
    }
    if(!backwardHeap3.get()) {
        backwardHeap3.reset(new QueryHeap(number_of_nodes));
    } else {
        backwardHeap3->Clear();
    }
}
<commit_msg>reverse inverted logic<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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.

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 HOLDER 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.

*/

#include "SearchEngineData.h"

void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
{
    if (forwardHeap.get())
    {
        forwardHeap->Clear();
    }
    else
    {
        forwardHeap.reset(new QueryHeap(number_of_nodes));
    }

    if (backwardHeap.get())
    {
        backwardHeap->Clear();
    }
    else
    {
        backwardHeap.reset(new QueryHeap(number_of_nodes));
    }
}

void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
{
    if (forwardHeap2.get())
    {
        forwardHeap2->Clear();
    }
    else
    {
        forwardHeap2.reset(new QueryHeap(number_of_nodes));
    }

    if (backwardHeap2.get())
    {
        backwardHeap2->Clear();
    }
    else
    {
        backwardHeap2.reset(new QueryHeap(number_of_nodes));
    }
}

void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
{
    if (forwardHeap3.get())
    {
        forwardHeap3->Clear();
    }
    else
    {
        forwardHeap3.reset(new QueryHeap(number_of_nodes));
    }

    if (backwardHeap3.get())
    {
        backwardHeap3->Clear();
    }
    else
    {
        backwardHeap3.reset(new QueryHeap(number_of_nodes));
    }
}
<|endoftext|>


<commit_before><commit_msg>fix Checkpoints_tests: use peercoin checkpoints<commit_after><|endoftext|>