<commit_before>/*
 * This file is part of the colouri.se project.
 * See the appropriate repository at http://colouri.se/.git for exact file
 * modification records.
*/

/*
 * Copyright (c) 2012, ef.gy Project Members
 *
 * 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 <ef.gy/http.h>
#include <ef.gy/fractions.h>
#include <ef.gy/colour-space-hsl.h>

#include <cstdlib>

#include <iostream>
#include <boost/regex.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>

#include <ef.gy/render-xml.h>

#include <ef.gy/continued-fractions.h>

using namespace efgy::colour;
using namespace efgy::math;
using namespace efgy::render;
using namespace boost::filesystem;
using namespace boost::iostreams;
using namespace boost::asio;
using namespace boost;
using namespace std;

class processColourise
{
    public:
        bool operator () (efgy::net::http::session<processColourise> &a)
        {
            static const regex rq
                ("/generated/(x?html|svg)/("
                  "(hsl:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?)"
                 "|(rgb:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?)"
                 ")(.(\\d+))?");
            boost::smatch matches;

            if (regex_match(a.resource, matches, rq))
            {
                string reply = string("<colour xmlns='http://colouri.se/2012'>")
                             + a.method + " " + a.resource
                             + "</colour>";

                unsigned long precision = 24;
                string sPrecision;

                if (matches[24].matched)
                {
                    sPrecision = matches[24];
                    precision = atoi(sPrecision.c_str());
                    sPrecision = "<precision>" + sPrecision + "</precision>";
                }

                if (matches[3].matched) // hsl:x:y:z
                {
                    long hNumerator = atoi(string(matches[4]).c_str());
                    long sNumerator = atoi(string(matches[7]).c_str());
                    long lNumerator = atoi(string(matches[10]).c_str());
                    long hDenominator = 1;
                    long sDenominator = 1;
                    long lDenominator = 1;

                    if (matches[6].matched)
                    {
                        hDenominator = atoi(string(matches[6]).c_str());
                        if (hDenominator == 0)
                        {
                            hNumerator = 0;
                            hDenominator = 1;
                        }
                    }
                    if (matches[9].matched)
                    {
                        sDenominator = atoi(string(matches[9]).c_str());
                        if (sDenominator == 0)
                        {
                            sNumerator = 0;
                            sDenominator = 1;
                        }
                    }
                    if (matches[12].matched)
                    {
                        lDenominator = atoi(string(matches[12]).c_str());
                        if (lDenominator == 0)
                        {
                            lNumerator = 0;
                            lDenominator = 1;
                        }
                    }

                    if (hNumerator >= hDenominator)
                    {
                        hNumerator %= hDenominator;
                    }

                    HSL<fraction>::value t (round(fraction(hNumerator, hDenominator), precision),
                                            round(fraction(sNumerator, sDenominator), precision),
                                            round(fraction(lNumerator, lDenominator), precision));

                    reply  = "<set xmlns='http://colouri.se/2012'>";
                    if (sPrecision != "")
                    {
                        reply += sPrecision;
                    }
                    reply += xml(t, false, precision);

                    RGB<fraction>::value tr = t;
                    reply += xml(tr, false, precision);

                    reply += xmlpicker (t, precision);

                    reply += "</set>";
                }

                if (matches[13].matched) // rgb:x:y:z
                {
                    long rNumerator = atoi(string(matches[14]).c_str());
                    long gNumerator = atoi(string(matches[17]).c_str());
                    long bNumerator = atoi(string(matches[20]).c_str());
                    long rDenominator = 1;
                    long gDenominator = 1;
                    long bDenominator = 1;

                    if (matches[16].matched)
                    {
                        rDenominator = atoi(string(matches[16]).c_str());
                        if (rDenominator == 0)
                        {
                            rNumerator = 0;
                            rDenominator = 1;
                        }
                    }
                    if (matches[19].matched)
                    {
                        gDenominator = atoi(string(matches[19]).c_str());
                        if (gDenominator == 0)
                        {
                            gNumerator = 0;
                            gDenominator = 1;
                        }
                    }
                    if (matches[22].matched)
                    {
                        bDenominator = atoi(string(matches[22]).c_str());
                        if (bDenominator == 0)
                        {
                            bNumerator = 0;
                            bDenominator = 1;
                        }
                    }

                    RGB<fraction>::value t (round(fraction(rNumerator, rDenominator), precision),
                                            round(fraction(gNumerator, gDenominator), precision),
                                            round(fraction(bNumerator, bDenominator), precision));

                    reply  = "<set xmlns='http://colouri.se/2012'>";
                    if (sPrecision != "")
                    {
                        reply += sPrecision;
                    }
                    reply += xml(t, false, precision);

                    HSL<fraction>::value tr = t;
                    reply += xml(tr, false, precision);

                    reply += xmlpicker (t, precision);

                    reply += "</set>";
                }

                a.reply (200,
                         "Content-Type: text/xml; charset=utf-8\r\n",
                         string("<?xml version='1.0' encoding='utf-8'?>")
                         + reply);
            }
            else
            {
                a.reply (404,
                         "Content-Type: text/xml; charset=utf-8\r\n",
                         "<?xml version='1.0' encoding='utf-8'?>"
                         "<error xmlns='http://colouri.se/2012'>404</error>");
            }

            return true;
        }
};

int main (int argc, char* argv[])
{
    try
    {
        if (argc != 2)
        {
            std::cerr << "Usage: colourise <socket>\n";
            return 1;
        }

        boost::asio::io_service io_service;

        efgy::net::http::server<processColourise> s(io_service, argv[1]);

        io_service.run();
    }
    catch (std::exception &e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}
<commit_msg>no longer need cstdlib<commit_after>/*
 * This file is part of the colouri.se project.
 * See the appropriate repository at http://colouri.se/.git for exact file
 * modification records.
*/

/*
 * Copyright (c) 2012, ef.gy Project Members
 *
 * 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 <ef.gy/http.h>
#include <ef.gy/fractions.h>
#include <ef.gy/colour-space-hsl.h>

#include <iostream>
#include <boost/regex.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>

#include <ef.gy/render-xml.h>

#include <ef.gy/continued-fractions.h>

using namespace efgy::colour;
using namespace efgy::math;
using namespace efgy::render;
using namespace boost::filesystem;
using namespace boost::iostreams;
using namespace boost::asio;
using namespace boost;
using namespace std;

class processColourise
{
    public:
        bool operator () (efgy::net::http::session<processColourise> &a)
        {
            static const regex rq
                ("/generated/(x?html|svg)/("
                  "(hsl:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?)"
                 "|(rgb:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?:(-?\\d+)(/(-?\\d+))?)"
                 ")(.(\\d+))?");
            boost::smatch matches;

            if (regex_match(a.resource, matches, rq))
            {
                string reply = string("<colour xmlns='http://colouri.se/2012'>")
                             + a.method + " " + a.resource
                             + "</colour>";

                unsigned long precision = 24;
                string sPrecision;

                if (matches[24].matched)
                {
                    sPrecision = matches[24];
                    precision = atoi(sPrecision.c_str());
                    sPrecision = "<precision>" + sPrecision + "</precision>";
                }

                if (matches[3].matched) // hsl:x:y:z
                {
                    long hNumerator = atoi(string(matches[4]).c_str());
                    long sNumerator = atoi(string(matches[7]).c_str());
                    long lNumerator = atoi(string(matches[10]).c_str());
                    long hDenominator = 1;
                    long sDenominator = 1;
                    long lDenominator = 1;

                    if (matches[6].matched)
                    {
                        hDenominator = atoi(string(matches[6]).c_str());
                        if (hDenominator == 0)
                        {
                            hNumerator = 0;
                            hDenominator = 1;
                        }
                    }
                    if (matches[9].matched)
                    {
                        sDenominator = atoi(string(matches[9]).c_str());
                        if (sDenominator == 0)
                        {
                            sNumerator = 0;
                            sDenominator = 1;
                        }
                    }
                    if (matches[12].matched)
                    {
                        lDenominator = atoi(string(matches[12]).c_str());
                        if (lDenominator == 0)
                        {
                            lNumerator = 0;
                            lDenominator = 1;
                        }
                    }

                    if (hNumerator >= hDenominator)
                    {
                        hNumerator %= hDenominator;
                    }

                    HSL<fraction>::value t (round(fraction(hNumerator, hDenominator), precision),
                                            round(fraction(sNumerator, sDenominator), precision),
                                            round(fraction(lNumerator, lDenominator), precision));

                    reply  = "<set xmlns='http://colouri.se/2012'>";
                    if (sPrecision != "")
                    {
                        reply += sPrecision;
                    }
                    reply += xml(t, false, precision);

                    RGB<fraction>::value tr = t;
                    reply += xml(tr, false, precision);

                    reply += xmlpicker (t, precision);

                    reply += "</set>";
                }

                if (matches[13].matched) // rgb:x:y:z
                {
                    long rNumerator = atoi(string(matches[14]).c_str());
                    long gNumerator = atoi(string(matches[17]).c_str());
                    long bNumerator = atoi(string(matches[20]).c_str());
                    long rDenominator = 1;
                    long gDenominator = 1;
                    long bDenominator = 1;

                    if (matches[16].matched)
                    {
                        rDenominator = atoi(string(matches[16]).c_str());
                        if (rDenominator == 0)
                        {
                            rNumerator = 0;
                            rDenominator = 1;
                        }
                    }
                    if (matches[19].matched)
                    {
                        gDenominator = atoi(string(matches[19]).c_str());
                        if (gDenominator == 0)
                        {
                            gNumerator = 0;
                            gDenominator = 1;
                        }
                    }
                    if (matches[22].matched)
                    {
                        bDenominator = atoi(string(matches[22]).c_str());
                        if (bDenominator == 0)
                        {
                            bNumerator = 0;
                            bDenominator = 1;
                        }
                    }

                    RGB<fraction>::value t (round(fraction(rNumerator, rDenominator), precision),
                                            round(fraction(gNumerator, gDenominator), precision),
                                            round(fraction(bNumerator, bDenominator), precision));

                    reply  = "<set xmlns='http://colouri.se/2012'>";
                    if (sPrecision != "")
                    {
                        reply += sPrecision;
                    }
                    reply += xml(t, false, precision);

                    HSL<fraction>::value tr = t;
                    reply += xml(tr, false, precision);

                    reply += xmlpicker (t, precision);

                    reply += "</set>";
                }

                a.reply (200,
                         "Content-Type: text/xml; charset=utf-8\r\n",
                         string("<?xml version='1.0' encoding='utf-8'?>")
                         + reply);
            }
            else
            {
                a.reply (404,
                         "Content-Type: text/xml; charset=utf-8\r\n",
                         "<?xml version='1.0' encoding='utf-8'?>"
                         "<error xmlns='http://colouri.se/2012'>404</error>");
            }

            return true;
        }
};

int main (int argc, char* argv[])
{
    try
    {
        if (argc != 2)
        {
            std::cerr << "Usage: colourise <socket>\n";
            return 1;
        }

        boost::asio::io_service io_service;

        efgy::net::http::server<processColourise> s(io_service, argv[1]);

        io_service.run();
    }
    catch (std::exception &e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}
<|endoftext|>


<commit_before>
#include <string>
#include <iostream>
#include <fstream>

#include "../headers/util.h"
#include "../headers/graph.h"
#include "../headers/io.h"
#include "../headers/opRelate.h"
#include "../headers/MarkupSTL.h"

using namespace std;

#define TEST_DESCR 1
#define GEOM_A_IN 2
#define GEOM_A_OUT 4
#define GEOM_B_IN 8
#define GEOM_B_OUT 16
#define TEST_OP 32
#define TEST_RESULT 64
#define PRED 128

int main(int argC, char* argV[]) {
//	int out=TEST_DESCR+GEOM_A_IN+GEOM_A_OUT+GEOM_B_IN+GEOM_B_OUT+TEST_OP+TEST_RESULT;
	int out=TEST_DESCR+GEOM_A_IN+GEOM_B_IN+TEST_OP+TEST_RESULT;
//	int out=GEOM_A_IN+GEOM_B_IN+TEST_OP+TEST_RESULT+PRED;
//	int out=TEST_DESCR+GEOM_A_IN+GEOM_B_IN+TEST_OP+TEST_RESULT;
//	int out=TEST_DESCR+TEST_RESULT;
//	int out=0;
	int failed=0;
	int succeeded=0;
//	string source="d://test.xml";
	string source="./test.xml";
	string precisionModel="";
	string desc="";
	string geomAin="";
	string geomBin="";
	string geomAout="";
	string geomBout="";
	string opName="";
	string opSig="";
	string opRes="";
	int testCount=0;

	WKTReader *r = new WKTReader(GeometryFactory(PrecisionModel(),10));
	WKTWriter *w=new WKTWriter();
	Geometry *gA;
	Geometry *gB;

	CMarkupSTL xml;
	bool a=xml.Load(source.c_str());

	xml.ResetPos();
	xml.FindElem("run");
	xml.FindChildElem("precisionModel");
	precisionModel=xml.GetChildAttrib("type");
	cout << "Precision Model: " << precisionModel << endl;
	while (xml.FindChildElem("case")) {
		xml.IntoElem();
		testCount++;
		xml.FindChildElem("desc");
		desc=xml.GetChildData();
		if (out & TEST_DESCR) {
			cout << "Test #" << testCount << endl;
			cout << "\t" << desc << endl;
		}
		xml.FindChildElem("a");
		geomAin=xml.GetChildData();
		gA=r->read(geomAin);
		geomAout=w->write(gA);
		if (out &(GEOM_A_IN | GEOM_A_OUT)) {
			cout << "\tGeometry A" << endl;
			if (out & GEOM_A_IN)
				cout << "\t\tIn:" << geomAin << endl;
			if (out & GEOM_A_OUT)
				cout << "\t\tOut:" << geomAout << endl;
		}

		xml.FindChildElem("b");
		geomBin=xml.GetChildData();
		gB=r->read(geomBin);
		geomBout=w->write(gB);
		if (out &(GEOM_B_IN | GEOM_B_OUT)) {
			cout << "\tGeometry B" << endl;
			if (out & GEOM_B_IN)
				cout << "\t\tIn:" << geomBin << endl;
			if (out & GEOM_B_OUT)
				cout << "\t\tOut:" << geomBout << endl;
		}

		xml.FindChildElem("test");
		xml.IntoElem();
        xml.FindChildElem("op");
		opName=xml.GetChildAttrib("name");
		opSig=xml.GetChildAttrib("arg3");
		opRes=xml.GetChildData();
		if (out & TEST_OP)
			cout << "\tOperation '" << opName << "[" << opSig <<"]' should be " << opRes << endl;
		if (opName=="relate") {
			IntersectionMatrix im(gA->relate(gB));
			if (out & TEST_RESULT)
				cout << "\tResult: matrix='" << im.toString() << "' result=" << (im.matches(opSig)?"true":"false") <<endl;
			if (!im.matches(opSig)) failed++; else succeeded++;
		}
		if (out & PRED) {
			cout << "\tEquals:\t\tAB=" << (gA->equals(gB)?"T":"F") << ", BA=" << (gB->equals(gA)?"T":"F") << endl;
			cout << "\tDisjoint:\tAB=" << (gA->disjoint(gB)?"T":"F") << ", BA=" << (gB->disjoint(gA)?"T":"F") << endl;
			cout << "\tIntersects:\tAB=" << (gA->intersects(gB)?"T":"F") << ", BA=" << (gB->intersects(gA)?"T":"F") << endl;
			cout << "\tTouches:\tAB=" << (gA->touches(gB)?"T":"F") << ", BA=" << (gB->touches(gA)?"T":"F") << endl;
			cout << "\tCrosses:\tAB=" << (gA->crosses(gB)?"T":"F") << ", BA=" << (gB->crosses(gA)?"T":"F") << endl;
			cout << "\tWithin:\t\tAB=" << (gA->within(gB)?"T":"F") << ", BA=" << (gB->within(gA)?"T":"F") << endl;
			cout << "\tContains:\tAB=" << (gA->contains(gB)?"T":"F") << ", BA=" << (gB->contains(gA)?"T":"F") << endl;
			cout << "\tOverlaps:\tAB=" << (gA->overlaps(gB)?"T":"F") << ", BA=" << (gB->overlaps(gA)?"T":"F") << endl;
		}

		xml.OutOfElem();
		xml.OutOfElem();
	}
	cout << "Failed: ";
	cout << failed << endl;
	cout << "Succeeded: ";
	cout << succeeded << endl;
	cout << "End Test";
}
<commit_msg>Fix headers.<commit_after>
#include <string>
#include <iostream>
#include <fstream>

#include "../headers/util.h"
#include "../headers/graph.h"
#include "../headers/io.h"
#include "../headers/opRelate.h"
#include "../io/markup/MarkupSTL.h"

using namespace std;

#define TEST_DESCR 1
#define GEOM_A_IN 2
#define GEOM_A_OUT 4
#define GEOM_B_IN 8
#define GEOM_B_OUT 16
#define TEST_OP 32
#define TEST_RESULT 64
#define PRED 128

int main(int argC, char* argV[]) {
//	int out=TEST_DESCR+GEOM_A_IN+GEOM_A_OUT+GEOM_B_IN+GEOM_B_OUT+TEST_OP+TEST_RESULT;
	int out=TEST_DESCR+GEOM_A_IN+GEOM_B_IN+TEST_OP+TEST_RESULT;
//	int out=GEOM_A_IN+GEOM_B_IN+TEST_OP+TEST_RESULT+PRED;
//	int out=TEST_DESCR+GEOM_A_IN+GEOM_B_IN+TEST_OP+TEST_RESULT;
//	int out=TEST_DESCR+TEST_RESULT;
//	int out=0;
	int failed=0;
	int succeeded=0;
//	string source="d://test.xml";
	string source="./test.xml";
	string precisionModel="";
	string desc="";
	string geomAin="";
	string geomBin="";
	string geomAout="";
	string geomBout="";
	string opName="";
	string opSig="";
	string opRes="";
	int testCount=0;

	WKTReader *r = new WKTReader(GeometryFactory(PrecisionModel(),10));
	WKTWriter *w=new WKTWriter();
	Geometry *gA;
	Geometry *gB;

	CMarkupSTL xml;
	bool a=xml.Load(source.c_str());

	xml.ResetPos();
	xml.FindElem("run");
	xml.FindChildElem("precisionModel");
	precisionModel=xml.GetChildAttrib("type");
	cout << "Precision Model: " << precisionModel << endl;
	while (xml.FindChildElem("case")) {
		xml.IntoElem();
		testCount++;
		xml.FindChildElem("desc");
		desc=xml.GetChildData();
		if (out & TEST_DESCR) {
			cout << "Test #" << testCount << endl;
			cout << "\t" << desc << endl;
		}
		xml.FindChildElem("a");
		geomAin=xml.GetChildData();
		gA=r->read(geomAin);
		geomAout=w->write(gA);
		if (out &(GEOM_A_IN | GEOM_A_OUT)) {
			cout << "\tGeometry A" << endl;
			if (out & GEOM_A_IN)
				cout << "\t\tIn:" << geomAin << endl;
			if (out & GEOM_A_OUT)
				cout << "\t\tOut:" << geomAout << endl;
		}

		xml.FindChildElem("b");
		geomBin=xml.GetChildData();
		gB=r->read(geomBin);
		geomBout=w->write(gB);
		if (out &(GEOM_B_IN | GEOM_B_OUT)) {
			cout << "\tGeometry B" << endl;
			if (out & GEOM_B_IN)
				cout << "\t\tIn:" << geomBin << endl;
			if (out & GEOM_B_OUT)
				cout << "\t\tOut:" << geomBout << endl;
		}

		xml.FindChildElem("test");
		xml.IntoElem();
        xml.FindChildElem("op");
		opName=xml.GetChildAttrib("name");
		opSig=xml.GetChildAttrib("arg3");
		opRes=xml.GetChildData();
		if (out & TEST_OP)
			cout << "\tOperation '" << opName << "[" << opSig <<"]' should be " << opRes << endl;
		if (opName=="relate") {
			IntersectionMatrix im(gA->relate(gB));
			if (out & TEST_RESULT)
				cout << "\tResult: matrix='" << im.toString() << "' result=" << (im.matches(opSig)?"true":"false") <<endl;
			if (!im.matches(opSig)) failed++; else succeeded++;
		}
		if (out & PRED) {
			cout << "\tEquals:\t\tAB=" << (gA->equals(gB)?"T":"F") << ", BA=" << (gB->equals(gA)?"T":"F") << endl;
			cout << "\tDisjoint:\tAB=" << (gA->disjoint(gB)?"T":"F") << ", BA=" << (gB->disjoint(gA)?"T":"F") << endl;
			cout << "\tIntersects:\tAB=" << (gA->intersects(gB)?"T":"F") << ", BA=" << (gB->intersects(gA)?"T":"F") << endl;
			cout << "\tTouches:\tAB=" << (gA->touches(gB)?"T":"F") << ", BA=" << (gB->touches(gA)?"T":"F") << endl;
			cout << "\tCrosses:\tAB=" << (gA->crosses(gB)?"T":"F") << ", BA=" << (gB->crosses(gA)?"T":"F") << endl;
			cout << "\tWithin:\t\tAB=" << (gA->within(gB)?"T":"F") << ", BA=" << (gB->within(gA)?"T":"F") << endl;
			cout << "\tContains:\tAB=" << (gA->contains(gB)?"T":"F") << ", BA=" << (gB->contains(gA)?"T":"F") << endl;
			cout << "\tOverlaps:\tAB=" << (gA->overlaps(gB)?"T":"F") << ", BA=" << (gB->overlaps(gA)?"T":"F") << endl;
		}

		xml.OutOfElem();
		xml.OutOfElem();
	}
	cout << "Failed: ";
	cout << failed << endl;
	cout << "Succeeded: ";
	cout << succeeded << endl;
	cout << "End Test";
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <fstream>

struct Field {
  std::string name;
  std::string value;
};

using Fields = std::vector<Field>;

struct Entry {
  std::string type;
  std::string key;
  Fields fields;
  std::string comment;
};

using Entries = std::vector<Entry>;

enum ParserState {
  LIMBO,
  ENTRY_TYPE,
  ENTRY_KEY,
  FIELD_LIMBO,
  FIELD_NAME,
  FIELD_POST_EQUAL,
  FIELD_VALUE_TEXT,
  FIELD_VALUE_SPACE,
  COMMENT
};

enum FieldValueLimit {
  FVL_NONE,
  FVL_CURLY,
  FVL_QUOTE
};

static void make_lowercase(std::string& s) {
  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}

static std::string as_lowercase(std::string const& s) {
  std::string s2 = s;
  make_lowercase(s2);
  return s2;
}

static void print_entries(std::ostream& stream, Entries const& entries);

class Parser {
  ParserState state;
  int line;
  int column;
  int curly_depth;
  FieldValueLimit value_limit;
  Entries entries;

  bool is_curly(char c) {
    return c == '{' || c == '}';
  }

  void handle_curly(char c) {
    if (c == '{') ++curly_depth;
    if (c == '}') --curly_depth;
    if (curly_depth < 0) fail();
  }

  void fail() __attribute__((noreturn));

  bool field_value_ended(char c) {
    if (curly_depth != 0) return false;
    switch (value_limit) {
      case FVL_NONE: return c == ',';
      case FVL_CURLY: return c == '}';
      case FVL_QUOTE: return c == '"';
    }
  }

  bool iskey(char c) {
    return std::isalnum(c) || c == '-' || c == '_' ||
      c == '.' || c == ':';
  }

public:

  void run(std::istream& stream) {
    entries.clear();
    state = LIMBO;
    line = 1;
    column = 0;
    curly_depth = 0;
    char c;
    while (stream.get(c)) {
      if (c == '\n') {
        ++line;
        column = 0;
      } else {
        ++column;
      }
      switch (state) {
        case LIMBO:
          if (std::isspace(c)) break;
          else if (c == '@') {
            state = ENTRY_TYPE;
            entries.push_back(Entry());
          } else {
            entries.push_back(Entry());
            entries.back().type = "comment";
            entries.back().comment.push_back(c);
            state = COMMENT;
          }
        break;
        case ENTRY_TYPE:
          if (std::isspace(c)) {
            if (as_lowercase(entries.back().type) == "comment") {
              make_lowercase(entries.back().type);
              state = COMMENT;
            } else break;
          }
          else if (c == '{') {
            make_lowercase(entries.back().type);
            if (entries.back().type == "string") state = FIELD_LIMBO;
            else state = ENTRY_KEY;
          }
          else if (std::isalpha(c)) {
            entries.back().type.push_back(c);
          }
          else fail();
        break;
        case ENTRY_KEY:
          if (std::isspace(c)) break;
          else if (c == ',') {
            make_lowercase(entries.back().key);
            state = FIELD_LIMBO;
          }
          else if (iskey(c)) {
            entries.back().key.push_back(c);
          }
          else fail();
        break;
        case FIELD_LIMBO:
          if (std::isspace(c)) break;
          else if (std::isalpha(c)) {
            entries.back().fields.push_back(Field());
            entries.back().fields.back().name.push_back(c);
            state = FIELD_NAME;
          } else if (c == '}') state = LIMBO;
          else if (c == ',') break;
          else fail();
        break;
        case FIELD_NAME:
          if (std::isspace(c)) break;
          else if (std::isalpha(c)) {
            entries.back().fields.back().name.push_back(c);
          } else if (c == '=') {
            make_lowercase(entries.back().fields.back().name);
            state = FIELD_POST_EQUAL;
          } else fail();
        break;
        case FIELD_POST_EQUAL:
          if (std::isspace(c)) break;
          else if (c == '{') {
            state = FIELD_VALUE_TEXT;
            value_limit = FVL_CURLY;
          } else if (c == '"') {
            state = FIELD_VALUE_TEXT;
            value_limit = FVL_QUOTE;
          } else if (std::isprint(c)) {
            value_limit = FVL_NONE;
            if (is_curly(c)) handle_curly(c);
            entries.back().fields.back().value.push_back(c);
            state = FIELD_VALUE_TEXT;
          } else fail();
        break;
        case FIELD_VALUE_TEXT:
          if (std::isspace(c)) state = FIELD_VALUE_SPACE;
          else if (field_value_ended(c)) {
            state = FIELD_LIMBO;
          } else if (std::isprint(c)) {
            if (is_curly(c)) handle_curly(c);
            entries.back().fields.back().value.push_back(c);
          } else fail();
        break;
        case FIELD_VALUE_SPACE:
          if (std::isspace(c)) break;
          else if (field_value_ended(c)) {
            state = FIELD_LIMBO;
          } else if (std::isprint(c)) {
            if (is_curly(c)) handle_curly(c);
            entries.back().fields.back().value.push_back(' ');
            entries.back().fields.back().value.push_back(c);
            state = FIELD_VALUE_TEXT;
          } else fail();
        break;
        case COMMENT:
          if (c == '\n') state = LIMBO;
          else entries.back().comment.push_back(c);
        break;
      }
    }
    if (state != LIMBO) {
      std::cout << "File ended early\n";
      exit(-1);
    }
  }

};

void Parser::fail() {
  std::cout << "Parse error at line " << line << " column " << column;
  std::cout << " state \"";
  switch (state) {
    case LIMBO: std::cout << "limbo"; break;
    case ENTRY_TYPE: std::cout << "entry type"; break;
    case ENTRY_KEY: std::cout << "entry key"; break;
    case FIELD_LIMBO: std::cout << "field limbo"; break;
    case FIELD_NAME: std::cout << "field name"; break;
    case FIELD_POST_EQUAL: std::cout << "field post equal"; break;
    case FIELD_VALUE_TEXT: std::cout << "field value text"; break;
    case FIELD_VALUE_SPACE: std::cout << "field value space"; break;
    case COMMENT: std::cout << "comment"; break;
  }
  std::cout << "\"\n";
  print_entries(std::cout, entries);
  exit(-1);
}

static void print_field(std::ostream& stream, Field const& field, bool last) {
  stream << "  " << field.name << "={" << field.value << "}";
  if (!last) stream << ",";
  stream << '\n';
}

static void print_fields(std::ostream& stream, Fields const& fields) {
  if (fields.empty()) return;
  for (size_t i = 0; i < fields.size() - 1; ++i)
    print_field(stream, fields[i], false);
  print_field(stream, fields.back(), true);
}

static void print_entry(std::ostream& stream, Entry const& entry) {
  if (entry.type == "comment") {
    stream << entry.comment << '\n';
    return;
  }
  stream << "@" << entry.type << "{";
  if (entry.type != "string") stream << entry.key << ",";
  stream << "\n";
  print_fields(stream, entry.fields);
  stream << "}\n\n";
}

static void print_entries(std::ostream& stream, Entries const& entries) {
  for (auto entry : entries) print_entry(stream, entry);
}

int main(int argc, char** argv) {
  if (argc != 2) {
    std::cout << "usage: " << argv[0] << " input.bib\n";
    return -1;
  }
  std::ifstream file(argv[1]);
  Parser parser;
  parser.run(file);
}
<commit_msg>also allow some control chars in field names<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <fstream>

struct Field {
  std::string name;
  std::string value;
};

using Fields = std::vector<Field>;

struct Entry {
  std::string type;
  std::string key;
  Fields fields;
  std::string comment;
};

using Entries = std::vector<Entry>;

enum ParserState {
  LIMBO,
  ENTRY_TYPE,
  ENTRY_KEY,
  FIELD_LIMBO,
  FIELD_NAME,
  FIELD_POST_EQUAL,
  FIELD_VALUE_TEXT,
  FIELD_VALUE_SPACE,
  COMMENT
};

enum FieldValueLimit {
  FVL_NONE,
  FVL_CURLY,
  FVL_QUOTE
};

static void make_lowercase(std::string& s) {
  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}

static std::string as_lowercase(std::string const& s) {
  std::string s2 = s;
  make_lowercase(s2);
  return s2;
}

static void print_entries(std::ostream& stream, Entries const& entries);

static bool isident(char c) {
  return std::isalnum(c) || c == '-' || c == '_' ||
    c == '.' || c == ':';
}

class Parser {
  ParserState state;
  int line;
  int column;
  int curly_depth;
  FieldValueLimit value_limit;
  Entries entries;

  bool is_curly(char c) {
    return c == '{' || c == '}';
  }

  void handle_curly(char c) {
    if (c == '{') ++curly_depth;
    if (c == '}') --curly_depth;
    if (curly_depth < 0) fail();
  }

  void fail() __attribute__((noreturn));

  bool field_value_ended(char c) {
    if (curly_depth != 0) return false;
    switch (value_limit) {
      case FVL_NONE: return c == ',';
      case FVL_CURLY: return c == '}';
      case FVL_QUOTE: return c == '"';
    }
  }

public:

  void run(std::istream& stream) {
    entries.clear();
    state = LIMBO;
    line = 1;
    column = 0;
    curly_depth = 0;
    char c;
    while (stream.get(c)) {
      if (c == '\n') {
        ++line;
        column = 0;
      } else {
        ++column;
      }
      switch (state) {
        case LIMBO:
          if (std::isspace(c)) break;
          else if (c == '@') {
            state = ENTRY_TYPE;
            entries.push_back(Entry());
          } else {
            entries.push_back(Entry());
            entries.back().type = "comment";
            entries.back().comment.push_back(c);
            state = COMMENT;
          }
        break;
        case ENTRY_TYPE:
          if (std::isspace(c)) {
            if (as_lowercase(entries.back().type) == "comment") {
              make_lowercase(entries.back().type);
              state = COMMENT;
            } else break;
          }
          else if (c == '{') {
            make_lowercase(entries.back().type);
            if (entries.back().type == "string") state = FIELD_LIMBO;
            else state = ENTRY_KEY;
          }
          else if (std::isalpha(c)) {
            entries.back().type.push_back(c);
          }
          else fail();
        break;
        case ENTRY_KEY:
          if (std::isspace(c)) break;
          else if (c == ',') {
            make_lowercase(entries.back().key);
            state = FIELD_LIMBO;
          }
          else if (isident(c)) {
            entries.back().key.push_back(c);
          }
          else fail();
        break;
        case FIELD_LIMBO:
          if (std::isspace(c)) break;
          else if (std::isalpha(c)) {
            entries.back().fields.push_back(Field());
            entries.back().fields.back().name.push_back(c);
            state = FIELD_NAME;
          } else if (c == '}') state = LIMBO;
          else if (c == ',') break;
          else fail();
        break;
        case FIELD_NAME:
          if (std::isspace(c)) break;
          else if (isident(c)) {
            entries.back().fields.back().name.push_back(c);
          } else if (c == '=') {
            make_lowercase(entries.back().fields.back().name);
            state = FIELD_POST_EQUAL;
          } else fail();
        break;
        case FIELD_POST_EQUAL:
          if (std::isspace(c)) break;
          else if (c == '{') {
            state = FIELD_VALUE_TEXT;
            value_limit = FVL_CURLY;
          } else if (c == '"') {
            state = FIELD_VALUE_TEXT;
            value_limit = FVL_QUOTE;
          } else if (std::isprint(c)) {
            value_limit = FVL_NONE;
            if (is_curly(c)) handle_curly(c);
            entries.back().fields.back().value.push_back(c);
            state = FIELD_VALUE_TEXT;
          } else fail();
        break;
        case FIELD_VALUE_TEXT:
          if (std::isspace(c)) state = FIELD_VALUE_SPACE;
          else if (field_value_ended(c)) {
            state = FIELD_LIMBO;
          } else if (std::isprint(c)) {
            if (is_curly(c)) handle_curly(c);
            entries.back().fields.back().value.push_back(c);
          } else fail();
        break;
        case FIELD_VALUE_SPACE:
          if (std::isspace(c)) break;
          else if (field_value_ended(c)) {
            state = FIELD_LIMBO;
          } else if (std::isprint(c)) {
            if (is_curly(c)) handle_curly(c);
            entries.back().fields.back().value.push_back(' ');
            entries.back().fields.back().value.push_back(c);
            state = FIELD_VALUE_TEXT;
          } else fail();
        break;
        case COMMENT:
          if (c == '\n') state = LIMBO;
          else entries.back().comment.push_back(c);
        break;
      }
    }
    if (state != LIMBO) {
      std::cout << "File ended early\n";
      exit(-1);
    }
  }

};

void Parser::fail() {
  std::cout << "Parse error at line " << line << " column " << column;
  std::cout << " state \"";
  switch (state) {
    case LIMBO: std::cout << "limbo"; break;
    case ENTRY_TYPE: std::cout << "entry type"; break;
    case ENTRY_KEY: std::cout << "entry key"; break;
    case FIELD_LIMBO: std::cout << "field limbo"; break;
    case FIELD_NAME: std::cout << "field name"; break;
    case FIELD_POST_EQUAL: std::cout << "field post equal"; break;
    case FIELD_VALUE_TEXT: std::cout << "field value text"; break;
    case FIELD_VALUE_SPACE: std::cout << "field value space"; break;
    case COMMENT: std::cout << "comment"; break;
  }
  std::cout << "\"\n";
  print_entries(std::cout, entries);
  exit(-1);
}

static void print_field(std::ostream& stream, Field const& field, bool last) {
  stream << "  " << field.name << "={" << field.value << "}";
  if (!last) stream << ",";
  stream << '\n';
}

static void print_fields(std::ostream& stream, Fields const& fields) {
  if (fields.empty()) return;
  for (size_t i = 0; i < fields.size() - 1; ++i)
    print_field(stream, fields[i], false);
  print_field(stream, fields.back(), true);
}

static void print_entry(std::ostream& stream, Entry const& entry) {
  if (entry.type == "comment") {
    stream << entry.comment << '\n';
    return;
  }
  stream << "@" << entry.type << "{";
  if (entry.type != "string") stream << entry.key << ",";
  stream << "\n";
  print_fields(stream, entry.fields);
  stream << "}\n\n";
}

static void print_entries(std::ostream& stream, Entries const& entries) {
  for (auto entry : entries) print_entry(stream, entry);
}

int main(int argc, char** argv) {
  if (argc != 2) {
    std::cout << "usage: " << argv[0] << " input.bib\n";
    return -1;
  }
  std::ifstream file(argv[1]);
  Parser parser;
  parser.run(file);
}
<|endoftext|>


<commit_before>//
//  Lexer.c
//  Emojicode
//
//  Created by Theo Weidmann on 28.02.15.
//  Copyright (c) 2015 Theo Weidmann. All rights reserved.
//

#include "Lexer.hpp"
#include "CompilerError.hpp"
#include "EmojiTokenization.hpp"
#include "Emojis.h"

namespace EmojicodeCompiler {

Lexer::Lexer(SourceManager::File *source, std::string sourcePositionFile) :
        sourcePosition_(1, 0, std::move(sourcePositionFile)), source_(source) {
    skipWhitespace();

    loadOperatorSingleTokens();
    singleTokens_.emplace(E_WHITE_EXCLAMATION_MARK, TokenType::BeginArgumentList);
    singleTokens_.emplace(E_RED_EXCLAMATION_MARK, TokenType::EndArgumentList);
    singleTokens_.emplace(E_WHITE_QUESTION_MARK, TokenType::BeginInterrogativeArgumentList);
    singleTokens_.emplace(E_RED_QUESTION_MARK, TokenType::EndInterrogativeArgumentList);
    singleTokens_.emplace(E_RIGHT_FACING_FIST, TokenType::GroupBegin);
    singleTokens_.emplace(E_LEFT_FACING_FIST, TokenType::GroupEnd);
    singleTokens_.emplace(E_RIGHT_ARROW_CURVING_LEFT, TokenType::Return);
    singleTokens_.emplace(E_CLOCKWISE_RIGHTWARDS_AND_LEFTWARDS_OPEN_CIRCLE_ARROWS, TokenType::RepeatWhile);
    singleTokens_.emplace(E_CLOCKWISE_RIGHTWARDS_AND_LEFTWARDS_OPEN_CIRCLE_ARROWS_WITH_CIRCLED_ONE_OVERLAY,
                          TokenType::ForIn);
    singleTokens_.emplace(E_THUMBS_UP_SIGN, TokenType::BooleanTrue);
    singleTokens_.emplace(E_THUMBS_DOWN_SIGN, TokenType::BooleanFalse);
    singleTokens_.emplace(E_POLICE_CARS_LIGHT, TokenType::Error);
    singleTokens_.emplace(E_TANGERINE, TokenType::If);
    singleTokens_.emplace(E_LEMON, TokenType::ElseIf);
    singleTokens_.emplace(E_STRAWBERRY, TokenType::Else);
    singleTokens_.emplace(E_AVOCADO, TokenType::ErrorHandler);
    singleTokens_.emplace(E_GRAPES, TokenType::BlockBegin);
    singleTokens_.emplace(E_WATERMELON, TokenType::BlockEnd);
    singleTokens_.emplace(E_NEW_SIGN, TokenType::New);
    singleTokens_.emplace(E_DOG, TokenType::This);
    singleTokens_.emplace(E_BIOHAZARD, TokenType::Unsafe);
    singleTokens_.emplace(E_RIGHT_ARROW_CURVING_UP, TokenType::Super);
    singleTokens_.emplace(E_RIGHTWARDS_ARROW, TokenType::RightProductionOperator);
    singleTokens_.emplace(E_LEFTWARDS_ARROW, TokenType::LeftProductionOperator);
    singleTokens_.emplace(E_CRAYON, TokenType::Mutable);
}

void Lexer::loadOperatorSingleTokens() {
    singleTokens_.emplace(E_HEAVY_PLUS_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_MINUS_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_DIVISION_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_MULTIPLICATION_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_OPEN_HANDS, TokenType::Operator);
    singleTokens_.emplace(E_HANDSHAKE, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_LARGE_CIRCLE, TokenType::Operator);
    singleTokens_.emplace(E_ANGER_SYMBOL, TokenType::Operator);
    singleTokens_.emplace(E_CROSS_MARK, TokenType::Operator);
    singleTokens_.emplace(E_LEFT_POINTING_BACKHAND_INDEX, TokenType::Operator);
    singleTokens_.emplace(E_RIGHT_POINTING_BACKHAND_INDEX, TokenType::Operator);
    singleTokens_.emplace(E_PUT_LITTER_IN_ITS_SPACE, TokenType::Operator);
    singleTokens_.emplace(E_HANDS_RAISED_IN_CELEBRATION, TokenType::Operator);
    singleTokens_.emplace(E_FACE_WITH_STUCK_OUT_TONGUE_AND_WINKING_EYE, TokenType::Operator);
    singleTokens_.emplace(E_RED_EXCLAMATION_MARK_AND_QUESTION_MARK, TokenType::Operator);
}

void Lexer::skipWhitespace() {
    while (continue_ && detectWhitespace()) {
        nextCharOrEnd();
    }
}

bool Lexer::detectWhitespace() {
    if (isNewline()) {
        sourcePosition_.character = 0;
        sourcePosition_.line++;
        source_->endLine(i_ + 1);
        return true;
    }
    return isWhitespace();
}

void Lexer::nextChar() {
    if (!hasMoreChars()) {
        throw CompilerError(sourcePosition_, "Unexpected end of file.");
    }
    i_++;
    sourcePosition_.character++;
}

void Lexer::nextCharOrEnd() {
    if (hasMoreChars()) {
        nextChar();
    }
    else {
        continue_ = false;
    }
}

Token Lexer::lex() {
    auto token = readToken();
    skipWhitespace();
    return token;
}

Token Lexer::readToken() {
    Token token(sourcePosition_);
    TokenConstructionState constState;

    TokenState state = beginToken(&token, &constState) ? TokenState::Continues : TokenState::Ended;
    while (true) {
        if (state == TokenState::Ended) {
            token.validate();
            nextCharOrEnd();
            return token;
        }
        nextChar();
        state = continueToken(&token, &constState);
        if (state == TokenState::NextBegun) {
            token.validate();
            return token;
        }
        // Whitespace must be detected here so that this method returns on NextBegun without calling detectWhitespace()
        // as the detectWhitespace() would otherwise be called twice for the same character. (Here and in lex())
        detectWhitespace();
    }
}

bool Lexer::beginToken(Token *token, TokenConstructionState *constState) const {
    auto it = singleTokens_.find(codePoint());
    if (it != singleTokens_.end()) {
        token->type_ = it->second;
        token->value_.push_back(codePoint());
        return false;
    }

    switch (codePoint()) {
        case E_INPUT_SYMBOL_LATIN_LETTERS:
            token->type_ = TokenType::String;
            return true;
        case E_THOUGHT_BALLOON:
            token->type_ = TokenType::SinglelineComment;
            return true;
        case E_GREEN_TEXTBOOK:
            token->type_ = TokenType::DocumentationComment;
            return true;
        case E_KEYCAP_10:
            token->type_ = TokenType::Symbol;
            return true;
        case E_LEFT_POINTING_TRIANGLE:
        case E_RIGHT_POINTING_TRIANGLE:
            token->type_ = TokenType::Operator;
            token->value_.push_back(codePoint());
            return true;
        default:
            break;
    }

    if (('0' <= codePoint() && codePoint() <= '9') || codePoint() == '-' || codePoint() == '+') {
        token->type_ = TokenType::Integer;
        constState->isHex_ = false;
    }
    else if (isEmoji(codePoint())) {
        token->type_ = TokenType::Identifier;
    }
    else {
        token->type_ = TokenType::Variable;
    }
    token->value_.push_back(codePoint());
    return true;
}

Lexer::TokenState Lexer::continueToken(Token *token, TokenConstructionState *constState) const {
    switch (token->type()) {
        case TokenType::Identifier:
            return continueIdentifierToken(token, constState);
        case TokenType::Operator:
            return continueOperator(token);
        case TokenType::SinglelineComment:
            return continueSingleLineToken(token, constState);
        case TokenType::MultilineComment:
            return continueMultilineComment(constState);
        case TokenType::DocumentationComment:
            if (codePoint() == E_GREEN_TEXTBOOK) {
                return TokenState::Ended;
            }
            token->value_.push_back(codePoint());
            return TokenState::Continues;
        case TokenType::String:
            return continueStringToken(token, constState);
        case TokenType::Variable:
            return continueVariableToken(token);
        case TokenType::Integer:
            return continueIntegerToken(token, constState);
        case TokenType::Double:
            return continueDoubleToken(token);
        case TokenType::Symbol:
            token->value_.push_back(codePoint());
            return TokenState::Ended;
        default:
            throw std::logic_error("Lexer: Token continued but not handled.");
    }
}

Lexer::TokenState Lexer::continueMultilineComment(Lexer::TokenConstructionState *constState) const {
    if (!constState->commentDetermined_) {
        if (codePoint() == E_THOUGHT_BALLOON) {
            return TokenState::Ended;
        }
        constState->commentDetermined_ = true;
    }
    if (codePoint() == E_END_ARROW) {
        constState->commentDetermined_ = false;
    }
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueSingleLineToken(Token *token, TokenConstructionState *constState) const {
    if (!constState->commentDetermined_) {
        if (codePoint() == E_SOON_ARROW) {
            token->type_ = TokenType::MultilineComment;
        }
        else {
            constState->commentDetermined_ = true;
        }
    }

    if (isNewline()) {
        return TokenState::Ended;
    }
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueDoubleToken(Token *token) const {
    if ('0' <= codePoint() && codePoint() <= '9') {
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    return TokenState::NextBegun;
}

Lexer::TokenState Lexer::continueVariableToken(Token *token) const {
    // A variable can consist of everything except for whitespaces and identifiers (that is emojis)
    // isWhitespace used here because if it is whitespace, the detection will take place below
    if (isWhitespace() || isEmoji(codePoint())) {
        return TokenState::NextBegun;
    }

    token->value_.push_back(codePoint());
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueIntegerToken(Token *token, Lexer::TokenConstructionState *constState) const {
    if (('0' <= codePoint() && codePoint() <= '9') ||
        (((64 < codePoint() && codePoint() < 71) || (96 < codePoint() && codePoint() < 103)) &&
         constState->isHex_)) {
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if (codePoint() == '.') {
        token->type_ = TokenType::Double;
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if ((codePoint() == 'x' || codePoint() == 'X') && token->value_.size() == 1 && token->value_[0] == '0') {
        constState->isHex_ = true;
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if (codePoint() == ',') {
        return TokenState::Continues;
    }
    return TokenState::NextBegun;
}

Lexer::TokenState Lexer::continueStringToken(Token *token, Lexer::TokenConstructionState *constState) const {
    if (constState->escapeSequence_) {
        switch (codePoint()) {
            case E_INPUT_SYMBOL_LATIN_LETTERS:
            case E_CROSS_MARK:
                token->value_.push_back(codePoint());
                break;
            case 'n':
                token->value_.push_back('\n');
                break;
            case 't':
                token->value_.push_back('\t');
                break;
            case 'r':
                token->value_.push_back('\r');
                break;
            default: {
                throw CompilerError(sourcePosition_, "Unrecognized escape sequence ❌",
                                    utf8(std::u32string(1, codePoint())), ".");
            }
        }

        constState->escapeSequence_ = false;
    }
    else if (codePoint() == E_CROSS_MARK) {
        constState->escapeSequence_ = true;
        return TokenState::Continues;
    }
    else if (codePoint() == E_INPUT_SYMBOL_LATIN_LETTERS) {
        return TokenState::Ended;
    }

    token->value_.push_back(codePoint());
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueIdentifierToken(Token *token, Lexer::TokenConstructionState *constState) const {
    if (constState->foundZWJ_ && isEmoji(codePoint())) {
        token->value_.push_back(codePoint());
        constState->foundZWJ_ = false;
        return TokenState::Continues;
    }
    if ((isEmojiModifier(codePoint()) && isEmojiModifierBase(token->value_.back())) ||
        (isRegionalIndicator(codePoint()) && token->value().size() == 1 &&
         isRegionalIndicator(token->value().front()))) {
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if (codePoint() == 0x200D) {
        token->value_.push_back(codePoint());
        constState->foundZWJ_ = true;
        return TokenState::Continues;
    }
    if (codePoint() == 0xFE0F) {  // Emojicode ignores the Emoji modifier behind an emoji character
        return TokenState::Continues;
    }
    if (token->value_.front() == E_PERSON_SHRUGGING) {
        token->type_ = TokenType::NoValue;
    }
    return TokenState::NextBegun;
}

Lexer::TokenState Lexer::continueOperator(Token *token) const {
    if (codePoint() == 0xFE0F) {  // Emojicode ignores the Emoji modifier behind an emoji character
        return TokenState::Continues;
    }
    if (codePoint() == E_HANDS_RAISED_IN_CELEBRATION) {
        token->value_.push_back(codePoint());
        return TokenState::Ended;
    }
    return TokenState::NextBegun;
}

}  // namespace EmojicodeCompiler
<commit_msg>❌ Fix lexer bug<commit_after>//
//  Lexer.c
//  Emojicode
//
//  Created by Theo Weidmann on 28.02.15.
//  Copyright (c) 2015 Theo Weidmann. All rights reserved.
//

#include "Lexer.hpp"
#include "CompilerError.hpp"
#include "EmojiTokenization.hpp"
#include "Emojis.h"

namespace EmojicodeCompiler {

Lexer::Lexer(SourceManager::File *source, std::string sourcePositionFile) :
        sourcePosition_(1, 0, std::move(sourcePositionFile)), source_(source) {
    skipWhitespace();

    loadOperatorSingleTokens();
    singleTokens_.emplace(E_WHITE_EXCLAMATION_MARK, TokenType::BeginArgumentList);
    singleTokens_.emplace(E_RED_EXCLAMATION_MARK, TokenType::EndArgumentList);
    singleTokens_.emplace(E_WHITE_QUESTION_MARK, TokenType::BeginInterrogativeArgumentList);
    singleTokens_.emplace(E_RED_QUESTION_MARK, TokenType::EndInterrogativeArgumentList);
    singleTokens_.emplace(E_RIGHT_FACING_FIST, TokenType::GroupBegin);
    singleTokens_.emplace(E_LEFT_FACING_FIST, TokenType::GroupEnd);
    singleTokens_.emplace(E_RIGHT_ARROW_CURVING_LEFT, TokenType::Return);
    singleTokens_.emplace(E_CLOCKWISE_RIGHTWARDS_AND_LEFTWARDS_OPEN_CIRCLE_ARROWS, TokenType::RepeatWhile);
    singleTokens_.emplace(E_CLOCKWISE_RIGHTWARDS_AND_LEFTWARDS_OPEN_CIRCLE_ARROWS_WITH_CIRCLED_ONE_OVERLAY,
                          TokenType::ForIn);
    singleTokens_.emplace(E_THUMBS_UP_SIGN, TokenType::BooleanTrue);
    singleTokens_.emplace(E_THUMBS_DOWN_SIGN, TokenType::BooleanFalse);
    singleTokens_.emplace(E_POLICE_CARS_LIGHT, TokenType::Error);
    singleTokens_.emplace(E_TANGERINE, TokenType::If);
    singleTokens_.emplace(E_LEMON, TokenType::ElseIf);
    singleTokens_.emplace(E_STRAWBERRY, TokenType::Else);
    singleTokens_.emplace(E_AVOCADO, TokenType::ErrorHandler);
    singleTokens_.emplace(E_GRAPES, TokenType::BlockBegin);
    singleTokens_.emplace(E_WATERMELON, TokenType::BlockEnd);
    singleTokens_.emplace(E_NEW_SIGN, TokenType::New);
    singleTokens_.emplace(E_DOG, TokenType::This);
    singleTokens_.emplace(E_BIOHAZARD, TokenType::Unsafe);
    singleTokens_.emplace(E_RIGHT_ARROW_CURVING_UP, TokenType::Super);
    singleTokens_.emplace(E_RIGHTWARDS_ARROW, TokenType::RightProductionOperator);
    singleTokens_.emplace(E_LEFTWARDS_ARROW, TokenType::LeftProductionOperator);
    singleTokens_.emplace(E_CRAYON, TokenType::Mutable);
}

void Lexer::loadOperatorSingleTokens() {
    singleTokens_.emplace(E_HEAVY_PLUS_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_MINUS_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_DIVISION_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_MULTIPLICATION_SIGN, TokenType::Operator);
    singleTokens_.emplace(E_OPEN_HANDS, TokenType::Operator);
    singleTokens_.emplace(E_HANDSHAKE, TokenType::Operator);
    singleTokens_.emplace(E_HEAVY_LARGE_CIRCLE, TokenType::Operator);
    singleTokens_.emplace(E_ANGER_SYMBOL, TokenType::Operator);
    singleTokens_.emplace(E_CROSS_MARK, TokenType::Operator);
    singleTokens_.emplace(E_LEFT_POINTING_BACKHAND_INDEX, TokenType::Operator);
    singleTokens_.emplace(E_RIGHT_POINTING_BACKHAND_INDEX, TokenType::Operator);
    singleTokens_.emplace(E_PUT_LITTER_IN_ITS_SPACE, TokenType::Operator);
    singleTokens_.emplace(E_HANDS_RAISED_IN_CELEBRATION, TokenType::Operator);
    singleTokens_.emplace(E_FACE_WITH_STUCK_OUT_TONGUE_AND_WINKING_EYE, TokenType::Operator);
    singleTokens_.emplace(E_RED_EXCLAMATION_MARK_AND_QUESTION_MARK, TokenType::Operator);
}

void Lexer::skipWhitespace() {
    while (continue_ && detectWhitespace()) {
        nextCharOrEnd();
    }
}

bool Lexer::detectWhitespace() {
    if (isNewline()) {
        sourcePosition_.character = 0;
        sourcePosition_.line++;
        source_->endLine(i_ + 1);
        return true;
    }
    return isWhitespace();
}

void Lexer::nextChar() {
    if (!hasMoreChars()) {
        throw CompilerError(sourcePosition_, "Unexpected end of file.");
    }
    i_++;
    sourcePosition_.character++;
}

void Lexer::nextCharOrEnd() {
    if (hasMoreChars()) {
        nextChar();
    }
    else {
        continue_ = false;
    }
}

Token Lexer::lex() {
    auto token = readToken();
    skipWhitespace();
    return token;
}

Token Lexer::readToken() {
    Token token(sourcePosition_);
    TokenConstructionState constState;

    TokenState state = beginToken(&token, &constState) ? TokenState::Continues : TokenState::Ended;
    while (true) {
        if (state == TokenState::Ended) {
            token.validate();
            nextCharOrEnd();
            return token;
        }
        nextChar();
        state = continueToken(&token, &constState);
        if (state == TokenState::NextBegun) {
            token.validate();
            return token;
        }
        // Whitespace must be detected here so that this method returns on NextBegun without calling detectWhitespace()
        // as the detectWhitespace() would otherwise be called twice for the same character. (Here and in lex())
        detectWhitespace();
    }
}

bool Lexer::beginToken(Token *token, TokenConstructionState *constState) const {
    auto it = singleTokens_.find(codePoint());
    if (it != singleTokens_.end()) {
        token->type_ = it->second;
        token->value_.push_back(codePoint());
        return false;
    }

    switch (codePoint()) {
        case E_INPUT_SYMBOL_LATIN_LETTERS:
            token->type_ = TokenType::String;
            return true;
        case E_THOUGHT_BALLOON:
            token->type_ = TokenType::SinglelineComment;
            return true;
        case E_GREEN_TEXTBOOK:
            token->type_ = TokenType::DocumentationComment;
            return true;
        case E_KEYCAP_10:
            token->type_ = TokenType::Symbol;
            return true;
        case E_LEFT_POINTING_TRIANGLE:
        case E_RIGHT_POINTING_TRIANGLE:
            token->type_ = TokenType::Operator;
            token->value_.push_back(codePoint());
            return true;
        default:
            break;
    }

    if (('0' <= codePoint() && codePoint() <= '9') || codePoint() == '-' || codePoint() == '+') {
        token->type_ = TokenType::Integer;
        constState->isHex_ = false;
    }
    else if (isEmoji(codePoint())) {
        token->type_ = TokenType::Identifier;
    }
    else {
        token->type_ = TokenType::Variable;
    }
    token->value_.push_back(codePoint());
    return true;
}

Lexer::TokenState Lexer::continueToken(Token *token, TokenConstructionState *constState) const {
    switch (token->type()) {
        case TokenType::Identifier:
            return continueIdentifierToken(token, constState);
        case TokenType::Operator:
            return continueOperator(token);
        case TokenType::SinglelineComment:
            return continueSingleLineToken(token, constState);
        case TokenType::MultilineComment:
            return continueMultilineComment(constState);
        case TokenType::DocumentationComment:
            if (codePoint() == E_GREEN_TEXTBOOK) {
                return TokenState::Ended;
            }
            token->value_.push_back(codePoint());
            return TokenState::Continues;
        case TokenType::String:
            return continueStringToken(token, constState);
        case TokenType::Variable:
            return continueVariableToken(token);
        case TokenType::Integer:
            return continueIntegerToken(token, constState);
        case TokenType::Double:
            return continueDoubleToken(token);
        case TokenType::Symbol:
            token->value_.push_back(codePoint());
            return TokenState::Ended;
        default:
            throw std::logic_error("Lexer: Token continued but not handled.");
    }
}

Lexer::TokenState Lexer::continueMultilineComment(Lexer::TokenConstructionState *constState) const {
    if (!constState->commentDetermined_) {
        if (codePoint() == E_THOUGHT_BALLOON) {
            return TokenState::Ended;
        }
        constState->commentDetermined_ = true;
    }
    if (codePoint() == E_END_ARROW) {
        constState->commentDetermined_ = false;
    }
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueSingleLineToken(Token *token, TokenConstructionState *constState) const {
    if (!constState->commentDetermined_) {
        if (codePoint() == E_SOON_ARROW) {
            token->type_ = TokenType::MultilineComment;
        }
        else {
            constState->commentDetermined_ = true;
        }
    }

    if (isNewline()) {
        return TokenState::Ended;
    }
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueDoubleToken(Token *token) const {
    if ('0' <= codePoint() && codePoint() <= '9') {
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    return TokenState::NextBegun;
}

Lexer::TokenState Lexer::continueVariableToken(Token *token) const {
    // A variable can consist of everything except for whitespaces and identifiers (that is emojis)
    // isWhitespace used here because if it is whitespace, the detection will take place below
    if (isWhitespace() || isEmoji(codePoint())) {
        return TokenState::NextBegun;
    }

    token->value_.push_back(codePoint());
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueIntegerToken(Token *token, Lexer::TokenConstructionState *constState) const {
    if (('0' <= codePoint() && codePoint() <= '9') ||
        (((64 < codePoint() && codePoint() < 71) || (96 < codePoint() && codePoint() < 103)) &&
         constState->isHex_)) {
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if (codePoint() == '.') {
        token->type_ = TokenType::Double;
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if ((codePoint() == 'x' || codePoint() == 'X') && token->value_.size() == 1 && token->value_[0] == '0') {
        constState->isHex_ = true;
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if (codePoint() == ',') {
        return TokenState::Continues;
    }
    return TokenState::NextBegun;
}

Lexer::TokenState Lexer::continueStringToken(Token *token, Lexer::TokenConstructionState *constState) const {
    if (constState->escapeSequence_) {
        switch (codePoint()) {
            case E_INPUT_SYMBOL_LATIN_LETTERS:
            case E_CROSS_MARK:
                token->value_.push_back(codePoint());
                break;
            case 'n':
                token->value_.push_back('\n');
                break;
            case 't':
                token->value_.push_back('\t');
                break;
            case 'r':
                token->value_.push_back('\r');
                break;
            default: {
                throw CompilerError(sourcePosition_, "Unrecognized escape sequence ❌",
                                    utf8(std::u32string(1, codePoint())), ".");
            }
        }

        constState->escapeSequence_ = false;
        return TokenState::Continues;
    }
    else if (codePoint() == E_CROSS_MARK) {
        constState->escapeSequence_ = true;
        return TokenState::Continues;
    }
    else if (codePoint() == E_INPUT_SYMBOL_LATIN_LETTERS) {
        return TokenState::Ended;
    }

    token->value_.push_back(codePoint());
    return TokenState::Continues;
}

Lexer::TokenState Lexer::continueIdentifierToken(Token *token, Lexer::TokenConstructionState *constState) const {
    if (constState->foundZWJ_ && isEmoji(codePoint())) {
        token->value_.push_back(codePoint());
        constState->foundZWJ_ = false;
        return TokenState::Continues;
    }
    if ((isEmojiModifier(codePoint()) && isEmojiModifierBase(token->value_.back())) ||
        (isRegionalIndicator(codePoint()) && token->value().size() == 1 &&
         isRegionalIndicator(token->value().front()))) {
        token->value_.push_back(codePoint());
        return TokenState::Continues;
    }
    if (codePoint() == 0x200D) {
        token->value_.push_back(codePoint());
        constState->foundZWJ_ = true;
        return TokenState::Continues;
    }
    if (codePoint() == 0xFE0F) {  // Emojicode ignores the Emoji modifier behind an emoji character
        return TokenState::Continues;
    }
    if (token->value_.front() == E_PERSON_SHRUGGING) {
        token->type_ = TokenType::NoValue;
    }
    return TokenState::NextBegun;
}

Lexer::TokenState Lexer::continueOperator(Token *token) const {
    if (codePoint() == 0xFE0F) {  // Emojicode ignores the Emoji modifier behind an emoji character
        return TokenState::Continues;
    }
    if (codePoint() == E_HANDS_RAISED_IN_CELEBRATION) {
        token->value_.push_back(codePoint());
        return TokenState::Ended;
    }
    return TokenState::NextBegun;
}

}  // namespace EmojicodeCompiler
<|endoftext|>


<commit_before>#include <osg/Notify>

#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>

#include "OSGA_Archive.h"

class ReaderWriterOSGA : public osgDB::ReaderWriter
{
public:
    ReaderWriterOSGA() { }

    virtual const char* className() const { return "OpenSceneGraph Archive Reader/Writer"; }
    virtual bool acceptsExtension(const std::string& extension)
    {
        return osgDB::equalCaseInsensitive(extension,"osga");
    }

    virtual ReadResult openArchive(const std::string& file,ArchiveStatus status, unsigned int indexBlockSize = 4096, const Options* = NULL)
    {
        std::string ext = osgDB::getLowerCaseFileExtension(file);
        if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

        std::string fileName = osgDB::findDataFile( file );
        if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

        osg::ref_ptr<OSGA_Archive> archive = new OSGA_Archive;
        if (!archive->open(fileName, status, indexBlockSize))
        {
            return ReadResult(ReadResult::FILE_NOT_HANDLED);
        }

        return archive.get();
    }

    virtual ReadResult readImage(const std::string& file,const Options* options)
    {
        ReadResult result = openArchive(file,osgDB::Archive::READ);

        if (!result.validArchive()) return result;

        osg::ref_ptr<ReaderWriter::Options> local_options = new ReaderWriter::Options;
        local_options->setDatabasePath(file);

        ReadResult result_2 = result.getArchive()->readImage(result.getArchive()->getMasterFileName(),local_options.get());

        // register the archive so that it is cached for future use.
        osgDB::Registry::instance()->addToArchiveCache(file, result.getArchive());

        return result_2;
    }

    virtual ReadResult readNode(const std::string& file,const Options* options)
    {
        ReadResult result = openArchive(file,osgDB::Archive::READ);

        if (!result.validArchive()) return result;

        osg::ref_ptr<ReaderWriter::Options> local_options = new ReaderWriter::Options;
        local_options->setDatabasePath(file);

        ReadResult result_2 = result.getArchive()->readNode(result.getArchive()->getMasterFileName(),local_options.get());

        // register the archive so that it is cached for future use.
        osgDB::Registry::instance()->addToArchiveCache(file, result.getArchive());

        return result_2;
    }

protected:

};

// register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterOSGA> g_osgaReaderWriterProxy;
<commit_msg>Fixed openArchive so that it only enforces the checking of the archive's existance when in READ mode.<commit_after>#include <osg/Notify>

#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>

#include "OSGA_Archive.h"

class ReaderWriterOSGA : public osgDB::ReaderWriter
{
public:
    ReaderWriterOSGA() { }

    virtual const char* className() const { return "OpenSceneGraph Archive Reader/Writer"; }
    virtual bool acceptsExtension(const std::string& extension)
    {
        return osgDB::equalCaseInsensitive(extension,"osga");
    }

    virtual ReadResult openArchive(const std::string& file,ArchiveStatus status, unsigned int indexBlockSize = 4096, const Options* = NULL)
    {

        std::string ext = osgDB::getLowerCaseFileExtension(file);
        if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

        std::string fileName = osgDB::findDataFile( file );
        if (fileName.empty())
        {
            if (status==READ) return ReadResult::FILE_NOT_FOUND;
            fileName = file;
        }

        osg::ref_ptr<OSGA_Archive> archive = new OSGA_Archive;
        if (!archive->open(fileName, status, indexBlockSize))
        {
            return ReadResult(ReadResult::FILE_NOT_HANDLED);
        }

        return archive.get();
    }

    virtual ReadResult readImage(const std::string& file,const Options* options)
    {
        ReadResult result = openArchive(file,osgDB::Archive::READ);

        if (!result.validArchive()) return result;

        osg::ref_ptr<ReaderWriter::Options> local_options = new ReaderWriter::Options;
        local_options->setDatabasePath(file);

        ReadResult result_2 = result.getArchive()->readImage(result.getArchive()->getMasterFileName(),local_options.get());

        // register the archive so that it is cached for future use.
        osgDB::Registry::instance()->addToArchiveCache(file, result.getArchive());

        return result_2;
    }

    virtual ReadResult readNode(const std::string& file,const Options* options)
    {
        ReadResult result = openArchive(file,osgDB::Archive::READ);

        if (!result.validArchive()) return result;

        osg::ref_ptr<ReaderWriter::Options> local_options = new ReaderWriter::Options;
        local_options->setDatabasePath(file);

        ReadResult result_2 = result.getArchive()->readNode(result.getArchive()->getMasterFileName(),local_options.get());

        // register the archive so that it is cached for future use.
        osgDB::Registry::instance()->addToArchiveCache(file, result.getArchive());

        return result_2;
    }

protected:

};

// register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterOSGA> g_osgaReaderWriterProxy;
<|endoftext|>


<commit_before>/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
 *
 * This software is open source and may be redistributed and/or modified under
 * the terms of the GNU General Public License (GPL) version 2.0.
 * The full license is in LICENSE.txt file included with this distribution,.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * include LICENSE.txt for more details.
*/

#include <osgPresentation/PickEventHandler>
#include <osgPresentation/SlideEventHandler>

#include <osgViewer/Viewer>
#include <osg/Notify>
#include <osgDB/FileUtils>

#include <stdlib.h>

using namespace osgPresentation;

PickEventHandler::PickEventHandler(osgPresentation::Operation operation,bool relativeJump, int slideNum, int layerNum):
    _operation(operation),
    _relativeJump(relativeJump),
    _slideNum(slideNum),
    _layerNum(layerNum)
{
}

PickEventHandler::PickEventHandler(const std::string& str, osgPresentation::Operation operation,bool relativeJump, int slideNum, int layerNum):
    _command(str),
    _operation(operation),
    _relativeJump(relativeJump),
    _slideNum(slideNum),
    _layerNum(layerNum)
{
}

PickEventHandler::PickEventHandler(const osgPresentation::KeyPosition& keyPos,bool relativeJump, int slideNum, int layerNum):
    _keyPos(keyPos),
    _operation(osgPresentation::EVENT),
    _relativeJump(relativeJump),
    _slideNum(slideNum),
    _layerNum(layerNum)
{
}

bool PickEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
{
    switch(ea.getEventType())
    {
        case(osgGA::GUIEventAdapter::MOVE):
        case(osgGA::GUIEventAdapter::PUSH):
        case(osgGA::GUIEventAdapter::RELEASE):
        {
            osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
            osgUtil::LineSegmentIntersector::Intersections intersections;
            if (viewer->computeIntersections(ea.getX(),ea.getY(), nv->getNodePath(), intersections))
            {
                for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr=intersections.begin();
                    hitr!=intersections.end();
                    ++hitr)
                {
                    if (ea.getEventType()==osgGA::GUIEventAdapter::MOVE)
                    {
                        OSG_INFO<<"Tooltip..."<<std::endl;
                    }
                    else if (ea.getEventType()==osgGA::GUIEventAdapter::RELEASE)
                    {
                        doOperation();
                        return true;
                    }
                }
            }
            break;
        }
        case(osgGA::GUIEventAdapter::KEYDOWN):
        {
            //OSG_NOTICE<<"PickEventHandler KEYDOWN "<<(char)ea.getKey()<<std::endl;
            //if (object) OSG_NOTICE<<"    "<<object->className()<<std::endl;
            break;
        }
        default:
            break;
    }
    return false;
}

void PickEventHandler::accept(osgGA::GUIEventHandlerVisitor& v)
{
    v.visit(*this);
}

void PickEventHandler::getUsage(osg::ApplicationUsage& /*usage*/) const
{
}

void PickEventHandler::setRelativeJump(int slideNum, int layerNum)
{
    _relativeJump = true;
    _slideNum = slideNum;
    _layerNum = layerNum;
}

void PickEventHandler::setAbsoluteJump(int slideNum, int layerNum)
{
    _relativeJump = false;
    _slideNum = slideNum;
    _layerNum = layerNum;
}

void PickEventHandler::doOperation()
{
    switch(_operation)
    {
        case(osgPresentation::RUN):
        {
            OSG_NOTICE<<"Run "<<_command<<std::endl;

#if 0
            osgDB::FilePathList& paths = osgDB::getDataFilePathList();
            if (!paths.empty())
            {
            #ifdef _WIN32
                std::string delimintor(";");
            #else
                std::string delimintor(":");
            #endif
                std::string filepath("OSG_FILE_PATH=");

                bool needDeliminator = false;
                for(osgDB::FilePathList::iterator itr = paths.begin();
                    itr != paths.end();
                    ++itr)
                {
                    if (needDeliminator) filepath += delimintor;
                    filepath += *itr;
                    needDeliminator = true;
                }
                putenv( (char*) filepath.c_str());

                std::string binpath("PATH=");
                char* path = getenv("PATH");
                if (path) binpath += path;

                needDeliminator = true;
                for(osgDB::FilePathList::iterator itr = paths.begin();
                    itr != paths.end();
                    ++itr)
                {
                    if (needDeliminator) binpath += delimintor;
                    binpath += *itr;
                    needDeliminator = true;
                }
                putenv( (char*) binpath.c_str());

            }
#endif
            int result = system(_command.c_str());

            OSG_INFO<<"system("<<_command<<") result "<<result<<std::endl;

            break;
        }
        case(osgPresentation::LOAD):
        {
            OSG_NOTICE<<"Load "<<_command<<std::endl;
            break;
        }
        case(osgPresentation::EVENT):
        {
            OSG_INFO<<"Event "<<_keyPos._key<<" "<<_keyPos._x<<" "<<_keyPos._y<<std::endl;
            if (SlideEventHandler::instance()) SlideEventHandler::instance()->dispatchEvent(_keyPos);
            break;
        }
        case(osgPresentation::JUMP):
        {
            OSG_NOTICE<<"Requires jump "<<std::endl;
            break;
        }
    }

    if (requiresJump())
    {
        OSG_NOTICE<<"Requires jump "<<_relativeJump<<", "<<_slideNum<<", "<<_layerNum<<std::endl;

        if (_relativeJump)
        {
            int previousSlide = SlideEventHandler::instance()->getActiveSlide();
            int previousLayer = SlideEventHandler::instance()->getActiveLayer();
            int newSlide = previousSlide + _slideNum;
            int newLayer = previousLayer + _layerNum;
            if (newLayer<0)
            {
                newLayer = 0;
            }

            OSG_NOTICE<<"   jump to "<<newSlide<<", "<<newLayer<<std::endl;

            SlideEventHandler::instance()->selectSlide(newSlide, newLayer);
        }
        else
        {
            SlideEventHandler::instance()->selectSlide(_slideNum,_layerNum);
        }
    }
    else
    {
        OSG_NOTICE<<"No jump required."<<std::endl;
    }
}

<commit_msg>Added a half second sleep after calling system command when the command is run in the background so that this command has a chance to run and open a window before the calling present3D moves on to the next frame.<commit_after>/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
 *
 * This software is open source and may be redistributed and/or modified under
 * the terms of the GNU General Public License (GPL) version 2.0.
 * The full license is in LICENSE.txt file included with this distribution,.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * include LICENSE.txt for more details.
*/

#include <osgPresentation/PickEventHandler>
#include <osgPresentation/SlideEventHandler>

#include <osgViewer/Viewer>
#include <osg/Notify>
#include <osgDB/FileUtils>

#include <stdlib.h>

using namespace osgPresentation;

PickEventHandler::PickEventHandler(osgPresentation::Operation operation,bool relativeJump, int slideNum, int layerNum):
    _operation(operation),
    _relativeJump(relativeJump),
    _slideNum(slideNum),
    _layerNum(layerNum)
{
}

PickEventHandler::PickEventHandler(const std::string& str, osgPresentation::Operation operation,bool relativeJump, int slideNum, int layerNum):
    _command(str),
    _operation(operation),
    _relativeJump(relativeJump),
    _slideNum(slideNum),
    _layerNum(layerNum)
{
}

PickEventHandler::PickEventHandler(const osgPresentation::KeyPosition& keyPos,bool relativeJump, int slideNum, int layerNum):
    _keyPos(keyPos),
    _operation(osgPresentation::EVENT),
    _relativeJump(relativeJump),
    _slideNum(slideNum),
    _layerNum(layerNum)
{
}

bool PickEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
{
    switch(ea.getEventType())
    {
        case(osgGA::GUIEventAdapter::MOVE):
        case(osgGA::GUIEventAdapter::PUSH):
        case(osgGA::GUIEventAdapter::RELEASE):
        {
            osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
            osgUtil::LineSegmentIntersector::Intersections intersections;
            if (viewer->computeIntersections(ea.getX(),ea.getY(), nv->getNodePath(), intersections))
            {
                for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr=intersections.begin();
                    hitr!=intersections.end();
                    ++hitr)
                {
                    if (ea.getEventType()==osgGA::GUIEventAdapter::MOVE)
                    {
                        OSG_INFO<<"Tooltip..."<<std::endl;
                    }
                    else if (ea.getEventType()==osgGA::GUIEventAdapter::RELEASE)
                    {
                        doOperation();
                        return true;
                    }
                }
            }
            break;
        }
        case(osgGA::GUIEventAdapter::KEYDOWN):
        {
            //OSG_NOTICE<<"PickEventHandler KEYDOWN "<<(char)ea.getKey()<<std::endl;
            //if (object) OSG_NOTICE<<"    "<<object->className()<<std::endl;
            break;
        }
        default:
            break;
    }
    return false;
}

void PickEventHandler::accept(osgGA::GUIEventHandlerVisitor& v)
{
    v.visit(*this);
}

void PickEventHandler::getUsage(osg::ApplicationUsage& /*usage*/) const
{
}

void PickEventHandler::setRelativeJump(int slideNum, int layerNum)
{
    _relativeJump = true;
    _slideNum = slideNum;
    _layerNum = layerNum;
}

void PickEventHandler::setAbsoluteJump(int slideNum, int layerNum)
{
    _relativeJump = false;
    _slideNum = slideNum;
    _layerNum = layerNum;
}

void PickEventHandler::doOperation()
{
    switch(_operation)
    {
        case(osgPresentation::RUN):
        {
            OSG_NOTICE<<"Run "<<_command<<std::endl;

#if 0
            osgDB::FilePathList& paths = osgDB::getDataFilePathList();
            if (!paths.empty())
            {
            #ifdef _WIN32
                std::string delimintor(";");
            #else
                std::string delimintor(":");
            #endif
                std::string filepath("OSG_FILE_PATH=");

                bool needDeliminator = false;
                for(osgDB::FilePathList::iterator itr = paths.begin();
                    itr != paths.end();
                    ++itr)
                {
                    if (needDeliminator) filepath += delimintor;
                    filepath += *itr;
                    needDeliminator = true;
                }
                putenv( (char*) filepath.c_str());

                std::string binpath("PATH=");
                char* path = getenv("PATH");
                if (path) binpath += path;

                needDeliminator = true;
                for(osgDB::FilePathList::iterator itr = paths.begin();
                    itr != paths.end();
                    ++itr)
                {
                    if (needDeliminator) binpath += delimintor;
                    binpath += *itr;
                    needDeliminator = true;
                }
                putenv( (char*) binpath.c_str());

            }
#endif

            bool commandRunsInBackground = (_command.find("&")!=std::string::npos);

            int result = system(_command.c_str());

            OSG_INFO<<"system("<<_command<<") result "<<result<<std::endl;

            if (commandRunsInBackground)
            {
                // Sleep breifly while command runs in background to give it a chance to open
                // a window and obscure this present3D's window avoiding this present3D from
                // rendering anything new before the new window opens.
                OpenThreads::Thread::microSleep(500000); // half second sleep.
            }

            break;
        }
        case(osgPresentation::LOAD):
        {
            OSG_NOTICE<<"Load "<<_command<<std::endl;
            break;
        }
        case(osgPresentation::EVENT):
        {
            OSG_INFO<<"Event "<<_keyPos._key<<" "<<_keyPos._x<<" "<<_keyPos._y<<std::endl;
            if (SlideEventHandler::instance()) SlideEventHandler::instance()->dispatchEvent(_keyPos);
            break;
        }
        case(osgPresentation::JUMP):
        {
            OSG_NOTICE<<"Requires jump "<<std::endl;
            break;
        }
    }

    if (requiresJump())
    {
        OSG_NOTICE<<"Requires jump "<<_relativeJump<<", "<<_slideNum<<", "<<_layerNum<<std::endl;

        if (_relativeJump)
        {
            int previousSlide = SlideEventHandler::instance()->getActiveSlide();
            int previousLayer = SlideEventHandler::instance()->getActiveLayer();
            int newSlide = previousSlide + _slideNum;
            int newLayer = previousLayer + _layerNum;
            if (newLayer<0)
            {
                newLayer = 0;
            }

            OSG_NOTICE<<"   jump to "<<newSlide<<", "<<newLayer<<std::endl;

            SlideEventHandler::instance()->selectSlide(newSlide, newLayer);
        }
        else
        {
            SlideEventHandler::instance()->selectSlide(_slideNum,_layerNum);
        }
    }
    else
    {
        OSG_NOTICE<<"No jump required."<<std::endl;
    }
}

<|endoftext|>


<commit_before>#include <cmath>
#include <algorithm>
#include "convexity.h"

int orientation(Point p, Point q, Point r) {
    Point pq = q-p ;
    Point qr = r-q ;
    int det = pq[0]*qr[1] - pq[1]*qr[0] ;
    return (det==0)?0:(det>0?1:-1) ;
}

bool lexicalOrder(Point p, Point q) {
    if (p[0] == q[0])
        return p[1] < q[1] ;
    return p[0] < q[0] ;
}

class orientationOrder {
    Point p ;
public:
    orientationOrder(Point p0): p(p0) {}
    bool operator () (Point q, Point r) {
        return orientation(p,q,r) > 0 ;
    }
};

// Graham Scan
vector<Point> getConvexHull(const Domain &domain, const DigitalSet &object, const vector<Point> &brdr) {
    vector<Point> border(brdr) ;
    if(border.size() <= 2)
        return border ;

    auto min = min_element(border.begin(), border.end(), lexicalOrder) ;
    Point p0 = *min ;
    border.erase(min) ;

    // First step
    sort(border.begin(), border.end(), orientationOrder(p0)) ;

    // Second step
    vector<Point> convexHull ;
    convexHull.push_back(p0) ;
    convexHull.push_back(border[0]) ;

    for(unsigned i = 1 ; i < border.size()-1 ; i++) {
        Point q = convexHull.back() ;
        convexHull.pop_back() ;
        Point p = convexHull.back() ;
        Point r = border[i] ;
        while(orientation(p,q,r) <= 0 && convexHull.size() >= 1) {
            q = p;
            convexHull.pop_back() ;
            p = convexHull.back();
        }
        convexHull.push_back(q);
        convexHull.push_back(r);
    }

    return convexHull;
}

double getConvexHullArea(const Domain &domain, const DigitalSet &object, const vector<Point> &border) {
    vector<Point> convexHull = getConvexHull(domain, object, border) ;
    double area = 0.0;
    for(unsigned i = 0 ; i < convexHull.size() ; i++) {
        Point p = convexHull[i];
        Point q = convexHull[i+1];
        area += (p[0]*q[1] - p[1]*q[0]) / 2.0;
    }
    return abs(area) ;
}

double convexity(const Domain &domain, const DigitalSet &object, const vector<Point> &border) {
    double convexArea = getConvexHullArea(domain, object, border) ;
    double area = (double)object.size() ;
    cout << area << "/" << convexArea << endl ;
    return area/convexArea ;
}
<commit_msg>Fix #1<commit_after>#include <cmath>
#include <algorithm>
#include "convexity.h"

int orientation(Point p, Point q, Point r) {
    Point pq = q-p ;
    Point qr = r-q ;
    int det = pq[0]*qr[1] - pq[1]*qr[0] ;
    return (det==0)?0:(det>0?1:-1) ;
}

bool lexicalOrder(Point p, Point q) {
    if (p[0] == q[0])
        return p[1] < q[1] ;
    return p[0] < q[0] ;
}

class orientationOrder {
    Point p ;
public:
    orientationOrder(Point p0): p(p0) {}
    bool operator () (Point q, Point r) {
        return orientation(p,q,r) > 0 ;
    }
};

// Graham Scan
vector<Point> getConvexHull(const Domain &domain, const DigitalSet &object, const vector<Point> &brdr) {
    vector<Point> border(brdr) ;
    if(border.size() <= 2)
        return border ;

    auto min = min_element(border.begin(), border.end(), lexicalOrder) ;
    Point p0 = *min ;
    border.erase(min) ;

    // First step
    sort(border.begin(), border.end(), orientationOrder(p0)) ;

    // Second step
    vector<Point> convexHull ;
    convexHull.push_back(p0) ;
    convexHull.push_back(border[0]) ;

    for(unsigned i = 1 ; i < border.size()-1 ; i++) {
        Point q = convexHull.back() ;
        convexHull.pop_back() ;
        Point p = convexHull.back() ;
        Point r = border[i] ;
        while(orientation(p,q,r) <= 0 && convexHull.size() >= 1) {
            q = p;
            convexHull.pop_back() ;
            p = convexHull.back();
        }
        convexHull.push_back(q);
        convexHull.push_back(r);
    }

    return convexHull;
}

double getConvexHullArea(const Domain &domain, const DigitalSet &object, const vector<Point> &border) {
    vector<Point> convexHull = getConvexHull(domain, object, border) ;
    double area = 0.0;
    unsigned int n = convexHull.size();
    for(unsigned i = 0 ; i < n ; i++) {
        Point p = convexHull[i];
        Point q = convexHull[(i+1)%n];
        area += (p[0]*q[1] - p[1]*q[0]) / 2.0;
    }
    return abs(area) ;
}

double convexity(const Domain &domain, const DigitalSet &object, const vector<Point> &border) {
    double convexArea = getConvexHullArea(domain, object, border) ;
    double area = (double)object.size() ;
    cout << area << "/" << convexArea << endl ;
    return area/convexArea ;
}
<|endoftext|>