<commit_before>#include <osg/Version>
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>

#include <set>
#include <vector>
#include <iostream>
#include <fstream>

typedef std::pair<std::string, std::string> NamePair;
typedef std::set<NamePair> NameSet;

NamePair EmptyNamePair;

bool validName(const std::string& first)
{
    if (first.empty()) return false;
    if (first[0]<'A' || first[0]>'Z') return false;

    if (first.size()>=2 && (first[1]<'a' || first[1]>'z')) return false;

    if (first=="Added") return false;
    if (first=="CameraNode") return false;
    if (first=="CopyOp") return false;
    if (first=="Fixed") return false;
    if (first=="Creator") return false;
    if (first=="CullVisitor") return false;
    if (first=="Drawable") return false;
    if (first=="Geode") return false;
    if (first=="GeoSet") return false;
    if (first=="Image") return false;
    if (first=="Images/SolarSystem") return false;
    if (first=="IntersectVisitor") return false;
    if (first=="LongIDRecord") return false;
    if (first=="Makefile") return false;
    if (first=="Matrix") return false;
    if (first=="MemoryManager") return false;
    if (first=="MeshRecord") return false;
    if (first=="Multigen") return false;
    if (first=="NewCullVisitor") return false;
    if (first=="Output") return false;
    if (first=="PageLOD") return false;
    if (first=="Improved") return false;
    if (first=="PagedLOD") return false;
    if (first=="Referenced") return false;
    if (first=="StateAttribute") return false;
    if (first=="Switch") return false;
    if (first=="TechniqueEventHandler") return false;
    if (first=="Uniform") return false;
    if (first=="Vec*") return false;
    if (first=="Viewer") return false;
    if (first=="VisualStudio") return false;
    if (first=="X") return false;
    if (first=="Y") return false;
    if (first=="Producer") return false;
    if (first=="New") return false;
    if (first=="Removed") return false;
    if (first=="Ouput") return false;
    if (first=="ReaderWriters") return false;
    if (first=="NodeVisitor") return false;
    if (first=="Fixes") return false;
    if (first=="FontImplementation") return false;
    if (first=="DisplaySettings") return false;
    return true;
}

std::string typoCorrection(const std::string& name)
{
#if 0
    if (name=="") return "";
    if (name=="") return "";
    if (name=="") return "";
#endif
    if (name=="Sjolie") return "Sjlie";
    if (name=="Jose") return "Jos";
    if (name=="Tarantilils") return "Tarantilis";
    if (name=="Heirtlein") return "Hertlein";
    if (name=="Fredric") return "Frederic";
    if (name=="Geof") return "Geoff";
    if (name=="Sewel") return "Sewell";
    if (name=="Moule") return "Moiule";
    if (name=="Macro") return "Marco";
    if (name=="March") return "Marco";
    if (name=="Gronenger") return "Gronager";
    if (name=="Gronger") return "Gronager";
    if (name=="Wieblen") return "Weiblen";
    if (name=="Molishtan") return "Moloshtan";
    if (name=="Bistroviae") return "Bistrovic";
    if (name=="Christaiansen") return "Christiansen";
    if (name=="Daust") return "Daoust";
    if (name=="Daved") return "David";
    if (name=="Fred") return "Frederic";
    if (name=="Fredrick") return "Frederic";
    if (name=="Garrat") return "Garret";
    if (name=="Heirtlein") return "Heirtlein";
    if (name=="Hertlien") return "Hertlein";
    if (name=="Hi") return "He";
    if (name=="Inverson") return "Iverson";
    if (name=="Iversion") return "Iverson";
    if (name=="Jeoen") return "Joran";
    if (name=="Johnasen") return "Johansen";
    if (name=="Johhansen") return "Johansen";
    if (name=="Johnansen") return "Johansen";
    if (name=="Jolley") return "Jolly";
    if (name=="J") return "Jos";
    if (name=="Keuhne") return "Kuehne";
    if (name=="Kheune") return "Kuehne";
    if (name=="Lashari") return "Lashkari";
    if (name=="Laskari") return "Lashkari";
    if (name=="Mammond") return "Marmond";
    if (name=="Marz") return "Martz";
    if (name=="Molishtan") return "Molishtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Nicklov") return "Nikolov";
    if (name=="Olad") return "Olaf";
    if (name=="Osfied") return "Osfield";
    if (name=="Pail") return "Paul";
    if (name=="Sokolosky") return "Sokolowsky";
    if (name=="Sokolsky") return "Sokolowsky";
    if (name=="Sonda") return "Sondra";
    if (name=="Stansilav") return "Stanislav";
    if (name=="Stefan") return "Stephan";
    if (name=="Stell") return "Steel";
    if (name=="Xennon") return "Hanson";
    if (name=="Yfei") return "Yefei";
    return name;
}

void nameCorrection(NamePair& name)
{
    if (name.first=="Eric" && name.second=="Hammil")
    {
        name.first = "Chris";
        name.second = "Hanson";
    }
}

void lastValidCharacter(const std::string& name, unsigned int& pos,char c)
{
    for(unsigned int i=0;i<pos;++i)
    {
        if (name[i]==c)
        {
            pos = i;
            return;
        }
    }
}

void lastValidCharacter(const std::string& name, unsigned int& last)
{
    lastValidCharacter(name, last, '.');
    lastValidCharacter(name, last, ',');
    lastValidCharacter(name, last, '\'');
    lastValidCharacter(name, last, '/');
    lastValidCharacter(name, last, '\\');
    lastValidCharacter(name, last, ':');
    lastValidCharacter(name, last, ';');
    lastValidCharacter(name, last, ')');
}

NamePair createName(const std::string& first, const std::string& second)
{
    if (first.empty()) return EmptyNamePair;

    unsigned int last = first.size();

    lastValidCharacter(first, last);

    if (last==0) return EmptyNamePair;

    std::string name;

    name.append(first.begin(), first.begin()+last);

    if (!validName(name)) return EmptyNamePair;

    name = typoCorrection(name);

    if (second.empty()) return NamePair(name,"");

    if (!validName(second)) return NamePair(name,"");

    last = second.size();

    lastValidCharacter(second, last);

    if (last>0)
    {
        std::string surname(second.begin(), second.begin()+last);
        surname = typoCorrection(surname);

        return NamePair(name, surname);
    }

    return NamePair(name,"");
}

void readContributors(NameSet& names, const std::string& file)
{
    std::cout<<"readContributions(names,"<<file<<")"<<std::endl;

    std::ifstream fin(file.c_str());

    typedef std::vector< std::string > Words;
    Words words;
    while(fin)
    {
        std::string keyword;
        fin >> keyword;
        words.push_back(keyword);
    }

    std::string blank_string;

    for(unsigned int i=0; i< words.size(); ++i)
    {
        if (words[i]=="From" ||
            words[i]=="from" ||
            words[i]=="From:" ||
            words[i]=="from:")
        {
            if (i+2<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], words[i+2]);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=2;
            }
            else if (i+1<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], blank_string);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=1;
            }
        }
    }

    if (names.size()>1)
    {
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            )
        {
            if (itr->second.empty())
            {
                NameSet::iterator next_itr = itr;
                ++next_itr;

                if (next_itr!=names.end() && itr->first==next_itr->first)
                {
                    names.erase(itr);
                    itr = next_itr;
                }
                else
                {
                    ++itr;
                }
            }
            else
            {
                ++itr;
            }
        }
    }
}

void buildContributors(NameSet& names)
{
    names.insert(NamePair("Robert","Osfield"));
    names.insert(NamePair("Don","Burns"));
    names.insert(NamePair("Marco","Jez"));
}

int main( int argc, char **argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options]");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("-c or --contributors","Print out the contributors list.");
    arguments.getApplicationUsage()->addCommandLineOption("-r <file> or --read <file>","Read the changelog to generate an estimated contributors list.");

    printf( "%s\n", osgGetVersion() );

    bool printContributors = false;
    while ( arguments.read("-c") || arguments.read("--contributors")) printContributors = true;

    std::string changeLog;
    while ( arguments.read("-r",changeLog) || arguments.read("--read",changeLog)) printContributors = true;

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        std::cout<<arguments.getApplicationUsage()->getCommandLineUsage()<<std::endl;
        arguments.getApplicationUsage()->write(std::cout,arguments.getApplicationUsage()->getCommandLineOptions());
        return 1;
    }

    if (printContributors)
    {
        NameSet names;
        buildContributors(names);
        if (!changeLog.empty())
        {
            readContributors(names, changeLog);
        }

        std::cout<<names.size()<<" Contributors:"<<std::endl;
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            ++itr)
        {
            std::cout<<"  "<<itr->first<<" "<<itr->second<<std::endl;
        }
    }

    return 0;
}
<commit_msg>Further improvements to the name filtering.<commit_after>#include <osg/Version>
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>

#include <set>
#include <vector>
#include <iostream>
#include <fstream>

typedef std::pair<std::string, std::string> NamePair;
typedef std::set<NamePair> NameSet;

NamePair EmptyNamePair;

bool validName(const std::string& first)
{
    if (first.empty()) return false;
    if (first[0]<'A' || first[0]>'Z') return false;

    if (first.size()>=2 && (first[1]<'a' || first[1]>'z')) return false;

    if (first=="Added") return false;
    if (first=="CameraNode") return false;
    if (first=="CopyOp") return false;
    if (first=="Fixed") return false;
    if (first=="Creator") return false;
    if (first=="CullVisitor") return false;
    if (first=="Drawable") return false;
    if (first=="Geode") return false;
    if (first=="GeoSet") return false;
    if (first=="Image") return false;
    if (first=="Images/SolarSystem") return false;
    if (first=="IntersectVisitor") return false;
    if (first=="LongIDRecord") return false;
    if (first=="Makefile") return false;
    if (first=="Matrix") return false;
    if (first=="MemoryManager") return false;
    if (first=="MeshRecord") return false;
    if (first=="Multigen") return false;
    if (first=="NewCullVisitor") return false;
    if (first=="Output") return false;
    if (first=="PageLOD") return false;
    if (first=="Improved") return false;
    if (first=="PagedLOD") return false;
    if (first=="Referenced") return false;
    if (first=="StateAttribute") return false;
    if (first=="Switch") return false;
    if (first=="TechniqueEventHandler") return false;
    if (first=="Uniform") return false;
    if (first=="Vec*") return false;
    if (first=="Viewer") return false;
    if (first=="VisualStudio") return false;
    if (first=="X") return false;
    if (first=="Y") return false;
    if (first=="Producer") return false;
    if (first=="New") return false;
    if (first=="Removed") return false;
    if (first=="Ouput") return false;
    if (first=="ReaderWriters") return false;
    if (first=="NodeVisitor") return false;
    if (first=="Fixes") return false;
    if (first=="FontImplementation") return false;
    if (first=="DisplaySettings") return false;
    return true;
}

std::string typoCorrection(const std::string& name)
{
#if 0
    if (name=="") return "";
    if (name=="") return "";
    if (name=="") return "";
#endif
    if (name=="Bistroviae") return "Bistrovic";
    if (name=="Christaiansen") return "Christiansen";
    if (name=="Daust") return "Daoust";
    if (name=="Daved") return "David";
    if (name=="Fred") return "Frederic";
    if (name=="Fredrick") return "Frederic";
    if (name=="Fredric") return "Frederic";
    if (name=="Garrat") return "Garret";
    if (name=="Geof") return "Geoff";
    if (name=="Gronenger") return "Gronager";
    if (name=="Gronger") return "Gronager";
    if (name=="Heirtlein") return "Heirtlein";
    if (name=="Heirtlein") return "Hertlein";
    if (name=="Hertlien") return "Hertlein";
    if (name=="Hi") return "He";
    if (name=="Inverson") return "Iverson";
    if (name=="Iversion") return "Iverson";
    if (name=="Jeoen") return "Joran";
    if (name=="Johhansen") return "Johansen";
    if (name=="Johnansen") return "Johansen";
    if (name=="Johnasen") return "Johansen";
    if (name=="Jolley") return "Jolly";
    if (name=="Jose") return "Jos";
    if (name=="J") return "Jos";
    if (name=="Keuhne") return "Kuehne";
    if (name=="Kheune") return "Kuehne";
    if (name=="Lashari") return "Lashkari";
    if (name=="Laskari") return "Lashkari";
    if (name=="Macro") return "Marco";
    if (name=="Mammond") return "Marmond";
    if (name=="March") return "Marco";
    if (name=="Marz") return "Martz";
    if (name=="Molishtan") return "Molishtan";
    if (name=="Molishtan") return "Moloshtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Moule") return "Moiule";
    if (name=="Nicklov") return "Nikolov";
    if (name=="Olad") return "Olaf";
    if (name=="Osfied") return "Osfield";
    if (name=="Pail") return "Paul";
    if (name=="Sewel") return "Sewell";
    if (name=="Sjolie") return "Sjlie";
    if (name=="Sokolosky") return "Sokolowsky";
    if (name=="Sokolsky") return "Sokolowsky";
    if (name=="Sonda") return "Sondra";
    if (name=="Stansilav") return "Stanislav";
    if (name=="Stefan") return "Stephan";
    if (name=="Stell") return "Steel";
    if (name=="Tarantilils") return "Tarantilis";
    if (name=="Wieblen") return "Weiblen";
    if (name=="Xennon") return "Hanson";
    if (name=="Yfei") return "Yefei";
    if (name=="Oritz") return "Ortiz";
    return name;
}

void nameCorrection(NamePair& name)
{
    if (name.first=="Eric" && name.second=="Hammil")
    {
        name.first = "Chris";
        name.second = "Hanson";
    }
    if (name.first=="Nick" && name.second=="")
    {
        name.first = "Trajce";
        name.second = "Nikolov";
    }
    if (name.first=="Julia" && name.second=="Ortiz")
    {
        name.first = "Julian";
        name.second = "Ortiz";
    }
}

void lastValidCharacter(const std::string& name, unsigned int& pos,char c)
{
    for(unsigned int i=0;i<pos;++i)
    {
        if (name[i]==c)
        {
            pos = i;
            return;
        }
    }
}

void lastValidCharacter(const std::string& name, unsigned int& last)
{
    lastValidCharacter(name, last, '.');
    lastValidCharacter(name, last, ',');
    lastValidCharacter(name, last, '\'');
    lastValidCharacter(name, last, '/');
    lastValidCharacter(name, last, '\\');
    lastValidCharacter(name, last, ':');
    lastValidCharacter(name, last, ';');
    lastValidCharacter(name, last, ')');
}

NamePair createName(const std::string& first, const std::string& second)
{
    if (first.empty()) return EmptyNamePair;

    unsigned int last = first.size();

    lastValidCharacter(first, last);

    if (last==0) return EmptyNamePair;

    std::string name;

    name.append(first.begin(), first.begin()+last);

    if (!validName(name)) return EmptyNamePair;

    name = typoCorrection(name);

    if (second.empty()) return NamePair(name,"");

    if (!validName(second)) return NamePair(name,"");

    last = second.size();

    lastValidCharacter(second, last);

    if (last>0)
    {
        std::string surname(second.begin(), second.begin()+last);
        surname = typoCorrection(surname);

        return NamePair(name, surname);
    }

    return NamePair(name,"");
}

void readContributors(NameSet& names, const std::string& file)
{
    std::cout<<"readContributions(names,"<<file<<")"<<std::endl;

    std::ifstream fin(file.c_str());

    typedef std::vector< std::string > Words;
    Words words;
    while(fin)
    {
        std::string keyword;
        fin >> keyword;
        words.push_back(keyword);
    }

    std::string blank_string;

    for(unsigned int i=0; i< words.size(); ++i)
    {
        if (words[i]=="From" ||
            words[i]=="from" ||
            words[i]=="From:" ||
            words[i]=="from:")
        {
            if (i+2<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], words[i+2]);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=2;
            }
            else if (i+1<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], blank_string);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=1;
            }
        }
    }

    if (names.size()>1)
    {
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            )
        {
            if (itr->second.empty())
            {
                NameSet::iterator next_itr = itr;
                ++next_itr;

                if (next_itr!=names.end() && itr->first==next_itr->first)
                {
                    names.erase(itr);
                    itr = next_itr;
                }
                else
                {
                    ++itr;
                }
            }
            else
            {
                ++itr;
            }
        }
    }
}

void buildContributors(NameSet& names)
{
    names.insert(NamePair("Robert","Osfield"));
    names.insert(NamePair("Don","Burns"));
    names.insert(NamePair("Marco","Jez"));
}

int main( int argc, char **argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options]");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("-c or --contributors","Print out the contributors list.");
    arguments.getApplicationUsage()->addCommandLineOption("-r <file> or --read <file>","Read the changelog to generate an estimated contributors list.");

    printf( "%s\n", osgGetVersion() );

    bool printContributors = false;
    while ( arguments.read("-c") || arguments.read("--contributors")) printContributors = true;

    std::string changeLog;
    while ( arguments.read("-r",changeLog) || arguments.read("--read",changeLog)) printContributors = true;

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        std::cout<<arguments.getApplicationUsage()->getCommandLineUsage()<<std::endl;
        arguments.getApplicationUsage()->write(std::cout,arguments.getApplicationUsage()->getCommandLineOptions());
        return 1;
    }

    if (printContributors)
    {
        NameSet names;
        buildContributors(names);
        if (!changeLog.empty())
        {
            readContributors(names, changeLog);
        }

        std::cout<<names.size()<<" Contributors:"<<std::endl;
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            ++itr)
        {
            std::cout<<"  "<<itr->first<<" "<<itr->second<<std::endl;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "encoder.h"
#include <stdlib.h>
#include <stdio.h>

using namespace std;

encoder::encoder()
{
}

encoder::~encoder()
{
}

string encoder::to_string()
{
	return buf;
}

void encoder::add_item(const char *key, const char *value)
{
	while (*key != '\0')
	{
		if (*key == '/')
		{
			buf.append("@S", 2);
		}
		else if (*key == '@')
		{
			buf.append("@A", 2);
		}
		else
		{
			buf += *key;
		}

		key++;
	}

	buf.append("@=", 2);

	while (*value != '\0')
	{
		if (*value == '/')
		{
			buf.append("@S", 2);
		}
		else if (*value == '@')
		{
			buf.append("@A", 2);
		}
		else
		{
			buf += *value;
		}

		value++;
	}

	buf.append("/", 1);
}

void encoder::add_item(const char *key, const int value)
{
	char str[64] = {0};
	snprintf(str, sizeof(str), "%d", value);
	add_item(key, static_cast<const char *>(str));
}

decoder::decoder()
{
}

decoder::~decoder()
{
}

void decoder::parse(const char * data)
{
	arr.clear();

	if (*data == '\0')
	{
		return;
	}

	key_value kv;
	string buf;

	while (*data != '\0')
	{
		if (*data ==  '/')    //end char
		{

			kv.value = buf;
			buf.clear();

			arr.push_back(kv);

			kv.key.clear();
			kv.value.clear();

		}
		else if (*data == '@')
		{
			data++;

			if (*data == 'A')
			{
				buf += '@';
			}
			else if (*data == 'S')  // char '/'
			{
				buf += '/';
			}
			else if (*data == '=')  // key value separator
			{
				kv.key = buf;
				buf.clear();
			}
		}
		else
		{
			buf += *data;
		}

		data++;
	}

	if (*data == '\0' && *(data - 1) != '/') //末尾漏掉斜线/的情况
	{
		kv.value = buf;
		buf.clear();

		arr.push_back(kv);
	}
}

string decoder::get_item_as_string(const char *key)
{
	string value;

	for (int i = 0; i < arr.size(); i++)
	{
		if(arr[i].key == key)
		{
			value = arr[i].value;
			break;
		}
	}

	return value;
}

int decoder::get_item_as_int(const char *key)
{
	int value = 0;

	for (int i = 0; i < arr.size(); i++)
	{
		if(arr[i].key == key)
		{
			value = atoi(arr[i].value.c_str());
			break;
		}
	}

	return value;
}
<commit_msg>add cpp codec<commit_after>#include "encoder.h"
#include <stdlib.h>
#include <stdio.h>

using namespace std;

encoder::encoder()
{
}

encoder::~encoder()
{
}

string encoder::to_string()
{
	return buf;
}

void encoder::add_item(const char *key, const char *value)
{
	while (*key != '\0')
	{
		if (*key == '/')
		{
			buf.append("@S", 2);
		}
		else if (*key == '@')
		{
			buf.append("@A", 2);
		}
		else
		{
			buf += *key;
		}

		key++;
	}

	buf.append("@=", 2);

	while (*value != '\0')
	{
		if (*value == '/')
		{
			buf.append("@S", 2);
		}
		else if (*value == '@')
		{
			buf.append("@A", 2);
		}
		else
		{
			buf += *value;
		}

		value++;
	}

	buf.append("/", 1);
}

void encoder::add_item(const char *key, const int value)
{
	char str[64] = {0};
	snprintf(str, sizeof(str), "%d", value);
	add_item(key, static_cast<const char *>(str));
}

decoder::decoder()
{
}

decoder::~decoder()
{
}

void decoder::parse(const char * data)
{
	arr.clear();

	if (*data == '\0')
	{
		return;
	}

	key_value kv;
	string buf;

	while (*data != '\0')
	{
		if (*data ==  '/')
		{
			kv.value = buf;
			buf.clear();

			arr.push_back(kv);

			kv.key.clear();
			kv.value.clear();

		}
		else if (*data == '@')
		{
			data++;

			if (*data == 'A')
			{
				buf += '@';
			}
			else if (*data == 'S')
			{
				buf += '/';
			}
			else if (*data == '=')
			{
				kv.key = buf;
				buf.clear();
			}
		}
		else
		{
			buf += *data;
		}

		data++;
	}

	if (*data == '\0' && *(data - 1) != '/')
	{
		kv.value = buf;
		buf.clear();

		arr.push_back(kv);
	}
}

string decoder::get_item_as_string(const char *key)
{
	string value;

	for (int i = 0; i < arr.size(); i++)
	{
		if(arr[i].key == key)
		{
			value = arr[i].value;
			break;
		}
	}

	return value;
}

int decoder::get_item_as_int(const char *key)
{
	int value = 0;

	for (int i = 0; i < arr.size(); i++)
	{
		if(arr[i].key == key)
		{
			value = atoi(arr[i].value.c_str());
			break;
		}
	}

	return value;
}
<|endoftext|>


<commit_before>#include "stdafx.h"

const static InputElement elements[] = {
	CInputElement("POSITION", SF_R32G32B32_FLOAT, 0),
	CInputElement("COLOR", SF_R32G32B32_FLOAT, 12),
};

struct Vertex {
	Vec3 pos;
	Vec3 color;
};

struct PickingUBO {
	Mat matVP;
};

class Picking {
	VBOID vbo2d, vbo3d;
	UBOID ubo;
	AFRenderStates renderStates;
public:
	Picking();
	~Picking();
	void Update();
	void Draw2D();
	void Draw3D();
};

#define CLASSNAME "Picking"
#define GET_PICKING \
	Picking* p = (Picking*)luaL_checkudata(L, 1, CLASSNAME);	\
	if (!p) {	\
		return 0;	\
	}

class PickingBinder {
public:
	PickingBinder() {
		GetLuaBindFuncContainer().push_back([](lua_State* L) {
			static luaL_Reg methods[] = {
				{ "Update", [](lua_State* L) { GET_PICKING p->Update(); return 0; } },
				{ "Draw2D", [](lua_State* L) { GET_PICKING p->Draw2D(); return 0; } },
				{ "Draw3D", [](lua_State* L) { GET_PICKING p->Draw3D(); return 0; } },
				{ "__gc", [](lua_State* L) { GET_PICKING p->~Picking(); return 0; } },
				{ nullptr, nullptr },
			};
			aflBindClass(L, CLASSNAME, methods, [](lua_State* L) { void* u = lua_newuserdata(L, sizeof(Picking)); new (u) Picking(); return 1; });
		});
	}
} static binder;

Picking::Picking()
{
	ubo = afCreateUBO(sizeof(Mat));
	vbo2d = afCreateDynamicVertexBuffer(sizeof(Vertex) * 3);
	vbo3d = afCreateDynamicVertexBuffer(sizeof(Vertex) * 3);
	renderStates.Create("solid", dimof(elements), elements, BM_NONE, DSM_DEPTH_ENABLE, CM_DISABLE);
	Update();
}

Picking::~Picking()
{
	afSafeDeleteBuffer(ubo);
	afSafeDeleteBuffer(vbo2d);
	afSafeDeleteBuffer(vbo3d);
}

void ScreenPosToRay(const Vec2& scrPos, Vec3& nearPos, Vec3& farPos)
{
	Mat v, p;
	matrixMan.Get(MatrixMan::VIEW, v);
	matrixMan.Get(MatrixMan::PROJ, p);
	Mat vp = makeViewportMatrix(systemMisc.GetScreenSize());
	Mat mInv = inv(v * p * vp);
	Vec4 nearPos4 = transform(Vec4(scrPos.x, scrPos.y, NDC_SPACE_NEAR, 1), mInv);
	Vec4 farPos4 = transform(Vec4(scrPos.x, scrPos.y, NDC_SPACE_FAR, 1), mInv);
	nearPos = Vec3(nearPos4.x, nearPos4.y, nearPos4.z) / nearPos4.w;
	farPos = Vec3(farPos4.x, farPos4.y, farPos4.z) / farPos4.w;
}

bool RayVsTriangle(const Vec3& ray1, const Vec3& ray2, const Vec3 triangle[])
{
	Vec3 rayDir = ray2 - ray1;
	float inner[3];
	for (int i = 0; i < 3; i++) {
		const Vec3& a = triangle[i];
		const Vec3& b = triangle[(i + 1) % 3];
		inner[i] = dot(cross(ray1 - a, a - b), rayDir);
	}
	return (inner[0] < 0 && inner[1] < 0 && inner[2] < 0) || (inner[0] > 0 && inner[1] > 0 && inner[2] > 0);
}

void Picking::Update()
{
	Vertex v[3];
	float radian = (float)(std::fmod(GetTime(), 3) * M_PI * 2 / 3);
	float radius = 0.5f;
	float aspect = (float)systemMisc.GetScreenSize().x / systemMisc.GetScreenSize().y;
	for (int i = 0; i < 3; i++) {
		static Vec3 center(-0.7f, 0.7f, 0.f);
		radian += (float)M_PI * 2 / 3;
		v[i].pos = Vec3(std::sin(radian) / aspect, std::cos(radian), 0) * radius + center;
	}

	bool hit = true;

	Vec2 scrPos = systemMisc.GetScreenSize();
	Vec2 curPos = systemMisc.GetMousePos();

	Vec2 curPosInNDC = curPos / scrPos * Vec2(2, -2) + Vec2(-1, 1);

	// test
	Mat vp = makeViewportMatrix(scrPos);
	Vec3 transformed = transform(Vec3(curPos.x, curPos.y, 1), inv(vp));
	assert(std::abs(transformed.x - curPosInNDC.x) < 0.001f);
	assert(std::abs(transformed.y - curPosInNDC.y) < 0.001f);

	for (int i = 0; i < 3; i++) {
		Vec3 dir = v[(i + 1) % 3].pos - v[i].pos;
		Vec3 cursorDir = Vec3(curPosInNDC.x, curPosInNDC.y, 0) - v[i].pos;
		if (cross(dir, cursorDir).z > 0) {
			hit = false;
		}
	}

	for (int i = 0; i < 3; i++) {
		v[i].color = hit ? Vec3(i == 0, i == 1, i == 2) : Vec3(0.5, 0.5, 0.5);
	}

	afWriteBuffer(vbo2d, v, sizeof(v));

	radian = (float)(std::fmod(GetTime(), 10) * M_PI * 2 / 10);
	radius = 50.f;
	Vec3 triangle[3];
	for (int i = 0; i < 3; i++) {
		radian += (float)M_PI * 2 / 3;
		triangle[i] = v[i].pos = Vec3(std::sin(radian) * radius, std::cos(radian) * radius, 50.f);
		v[i].color = Vec3(0.5, 0.5, 0.5);
	}

	Vec3 n, f;
	ScreenPosToRay(systemMisc.GetMousePos(), n, f);
	hit = RayVsTriangle(n, f, triangle);
	for (int i = 0; i < 3; i++) {
		v[i].color = hit ? Vec3(i == 0, i == 1, i == 2) : Vec3(0.5, 0.5, 0.5);
	}

	afWriteBuffer(vbo3d, v, sizeof(v));
}

void Picking::Draw3D()
{
	renderStates.Apply();
	VBOID vbos[] = {vbo3d};
	int strides[] = {sizeof(Vertex)};
#ifdef GL_TRUE
	afSetVertexAttributes(elements, dimof(elements), 1, vbos, strides);
#endif
#ifdef __d3d11_h__
	ID3D11Buffer* d11Bufs[] = { vbo3d.Get() };
	UINT uStrides[] = { sizeof(Vertex) };
	UINT offsets[] = {0};
	deviceMan11.GetContext()->IASetVertexBuffers(0, dimof(d11Bufs), d11Bufs, uStrides, offsets);
#endif
	Mat mView, mProj;
	matrixMan.Get(MatrixMan::VIEW, mView);
	matrixMan.Get(MatrixMan::PROJ, mProj);
	Mat mVP = mView * mProj;
	afWriteBuffer(ubo, &mVP, sizeof(Mat));
	afBindBufferToBindingPoint(ubo, 0);

	afDraw(PT_TRIANGLESTRIP, 3);
}

void Picking::Draw2D()
{
	renderStates.Apply();
	VBOID vbos[] = {vbo2d};
	int strides[] = {sizeof(Vertex)};
#ifdef GL_TRUE
	afSetVertexAttributes(elements, dimof(elements), 1, vbos, strides);
#endif
#ifdef __d3d11_h__
	ID3D11Buffer* d11Bufs[] = { vbo2d.Get() };
	UINT uStrides[] = { sizeof(Vertex) };
	UINT offsets[] = { 0 };
	deviceMan11.GetContext()->IASetVertexBuffers(0, dimof(d11Bufs), d11Bufs, uStrides, offsets);
#endif

	PickingUBO buf;
	afWriteBuffer(ubo, &buf, sizeof(buf));
	afBindBufferToBindingPoint(ubo, 0);

	afDraw(PT_TRIANGLESTRIP, 3);
}
<commit_msg>Must declare using default VAO before bind vertex buffer attributes directly.<commit_after>#include "stdafx.h"

const static InputElement elements[] = {
	CInputElement("POSITION", SF_R32G32B32_FLOAT, 0),
	CInputElement("COLOR", SF_R32G32B32_FLOAT, 12),
};

struct Vertex {
	Vec3 pos;
	Vec3 color;
};

struct PickingUBO {
	Mat matVP;
};

class Picking {
	VBOID vbo2d, vbo3d;
	UBOID ubo;
	AFRenderStates renderStates;
public:
	Picking();
	~Picking();
	void Update();
	void Draw2D();
	void Draw3D();
};

#define CLASSNAME "Picking"
#define GET_PICKING \
	Picking* p = (Picking*)luaL_checkudata(L, 1, CLASSNAME);	\
	if (!p) {	\
		return 0;	\
	}

class PickingBinder {
public:
	PickingBinder() {
		GetLuaBindFuncContainer().push_back([](lua_State* L) {
			static luaL_Reg methods[] = {
				{ "Update", [](lua_State* L) { GET_PICKING p->Update(); return 0; } },
				{ "Draw2D", [](lua_State* L) { GET_PICKING p->Draw2D(); return 0; } },
				{ "Draw3D", [](lua_State* L) { GET_PICKING p->Draw3D(); return 0; } },
				{ "__gc", [](lua_State* L) { GET_PICKING p->~Picking(); return 0; } },
				{ nullptr, nullptr },
			};
			aflBindClass(L, CLASSNAME, methods, [](lua_State* L) { void* u = lua_newuserdata(L, sizeof(Picking)); new (u) Picking(); return 1; });
		});
	}
} static binder;

Picking::Picking()
{
	ubo = afCreateUBO(sizeof(Mat));
	vbo2d = afCreateDynamicVertexBuffer(sizeof(Vertex) * 3);
	vbo3d = afCreateDynamicVertexBuffer(sizeof(Vertex) * 3);
	renderStates.Create("solid", dimof(elements), elements, BM_NONE, DSM_DEPTH_ENABLE, CM_DISABLE);
	Update();
}

Picking::~Picking()
{
	afSafeDeleteBuffer(ubo);
	afSafeDeleteBuffer(vbo2d);
	afSafeDeleteBuffer(vbo3d);
}

void ScreenPosToRay(const Vec2& scrPos, Vec3& nearPos, Vec3& farPos)
{
	Mat v, p;
	matrixMan.Get(MatrixMan::VIEW, v);
	matrixMan.Get(MatrixMan::PROJ, p);
	Mat vp = makeViewportMatrix(systemMisc.GetScreenSize());
	Mat mInv = inv(v * p * vp);
	Vec4 nearPos4 = transform(Vec4(scrPos.x, scrPos.y, NDC_SPACE_NEAR, 1), mInv);
	Vec4 farPos4 = transform(Vec4(scrPos.x, scrPos.y, NDC_SPACE_FAR, 1), mInv);
	nearPos = Vec3(nearPos4.x, nearPos4.y, nearPos4.z) / nearPos4.w;
	farPos = Vec3(farPos4.x, farPos4.y, farPos4.z) / farPos4.w;
}

bool RayVsTriangle(const Vec3& ray1, const Vec3& ray2, const Vec3 triangle[])
{
	Vec3 rayDir = ray2 - ray1;
	float inner[3];
	for (int i = 0; i < 3; i++) {
		const Vec3& a = triangle[i];
		const Vec3& b = triangle[(i + 1) % 3];
		inner[i] = dot(cross(ray1 - a, a - b), rayDir);
	}
	return (inner[0] < 0 && inner[1] < 0 && inner[2] < 0) || (inner[0] > 0 && inner[1] > 0 && inner[2] > 0);
}

void Picking::Update()
{
	Vertex v[3];
	float radian = (float)(std::fmod(GetTime(), 3) * M_PI * 2 / 3);
	float radius = 0.5f;
	float aspect = (float)systemMisc.GetScreenSize().x / systemMisc.GetScreenSize().y;
	for (int i = 0; i < 3; i++) {
		static Vec3 center(-0.7f, 0.7f, 0.f);
		radian += (float)M_PI * 2 / 3;
		v[i].pos = Vec3(std::sin(radian) / aspect, std::cos(radian), 0) * radius + center;
	}

	bool hit = true;

	Vec2 scrPos = systemMisc.GetScreenSize();
	Vec2 curPos = systemMisc.GetMousePos();

	Vec2 curPosInNDC = curPos / scrPos * Vec2(2, -2) + Vec2(-1, 1);

	// test
	Mat vp = makeViewportMatrix(scrPos);
	Vec3 transformed = transform(Vec3(curPos.x, curPos.y, 1), inv(vp));
	assert(std::abs(transformed.x - curPosInNDC.x) < 0.001f);
	assert(std::abs(transformed.y - curPosInNDC.y) < 0.001f);

	for (int i = 0; i < 3; i++) {
		Vec3 dir = v[(i + 1) % 3].pos - v[i].pos;
		Vec3 cursorDir = Vec3(curPosInNDC.x, curPosInNDC.y, 0) - v[i].pos;
		if (cross(dir, cursorDir).z > 0) {
			hit = false;
		}
	}

	for (int i = 0; i < 3; i++) {
		v[i].color = hit ? Vec3(i == 0, i == 1, i == 2) : Vec3(0.5, 0.5, 0.5);
	}

	afWriteBuffer(vbo2d, v, sizeof(v));

	radian = (float)(std::fmod(GetTime(), 10) * M_PI * 2 / 10);
	radius = 50.f;
	Vec3 triangle[3];
	for (int i = 0; i < 3; i++) {
		radian += (float)M_PI * 2 / 3;
		triangle[i] = v[i].pos = Vec3(std::sin(radian) * radius, std::cos(radian) * radius, 50.f);
		v[i].color = Vec3(0.5, 0.5, 0.5);
	}

	Vec3 n, f;
	ScreenPosToRay(systemMisc.GetMousePos(), n, f);
	hit = RayVsTriangle(n, f, triangle);
	for (int i = 0; i < 3; i++) {
		v[i].color = hit ? Vec3(i == 0, i == 1, i == 2) : Vec3(0.5, 0.5, 0.5);
	}

	afWriteBuffer(vbo3d, v, sizeof(v));
}

void Picking::Draw3D()
{
	renderStates.Apply();
	VBOID vbos[] = {vbo3d};
	int strides[] = {sizeof(Vertex)};
#ifdef GL_TRUE
	afBindVAO(0);
	afSetVertexAttributes(elements, dimof(elements), 1, vbos, strides);
#endif
#ifdef __d3d11_h__
	ID3D11Buffer* d11Bufs[] = { vbo3d.Get() };
	UINT uStrides[] = { sizeof(Vertex) };
	UINT offsets[] = {0};
	deviceMan11.GetContext()->IASetVertexBuffers(0, dimof(d11Bufs), d11Bufs, uStrides, offsets);
#endif
	Mat mView, mProj;
	matrixMan.Get(MatrixMan::VIEW, mView);
	matrixMan.Get(MatrixMan::PROJ, mProj);
	Mat mVP = mView * mProj;
	afWriteBuffer(ubo, &mVP, sizeof(Mat));
	afBindBufferToBindingPoint(ubo, 0);

	afDraw(PT_TRIANGLESTRIP, 3);
}

void Picking::Draw2D()
{
	renderStates.Apply();
	VBOID vbos[] = {vbo2d};
	int strides[] = {sizeof(Vertex)};
#ifdef GL_TRUE
	afBindVAO(0);
	afSetVertexAttributes(elements, dimof(elements), 1, vbos, strides);
#endif
#ifdef __d3d11_h__
	ID3D11Buffer* d11Bufs[] = { vbo2d.Get() };
	UINT uStrides[] = { sizeof(Vertex) };
	UINT offsets[] = { 0 };
	deviceMan11.GetContext()->IASetVertexBuffers(0, dimof(d11Bufs), d11Bufs, uStrides, offsets);
#endif

	PickingUBO buf;
	afWriteBuffer(ubo, &buf, sizeof(buf));
	afBindBufferToBindingPoint(ubo, 0);

	afDraw(PT_TRIANGLESTRIP, 3);
}
<|endoftext|>


<commit_before>#include <cmath>
#include "glcamera.h"

#ifdef __APPLE__
    #include <GLUT/glut.h>
#else
    #include <glut.h>
#endif

#include <QDebug>

GLCamera::GLCamera()
{
    moveSpeed = 10.0;

    x = 0.0;
    y = 0.0;
    z = 1.0;

    look_x = 0.0;
    look_y = 0.0;
    look_z = 0.0;

    zoomLevel = 1.0;
    zoomSpeed = 0.05;

    // lat="46.791803,9" lon="4.427704,7"
    planeLeft = 437.0;
    planeRight = 449.0;

    planeBottom = 4674.0;
    planeTop = 4686.0;

    planeNear = 0.0;
    planeFar = 10.0;

    canvasWidth = 0;
    canvasHeight = 0;
}

void GLCamera::left()
{
    x -= (moveSpeed * (1 / std::abs(zoomLevel)));
    look_x -= (moveSpeed * (1 / std::abs(zoomLevel)));
}

void GLCamera::right()
{
    x += (moveSpeed * (1 / std::abs(zoomLevel)));;
    look_x += (moveSpeed * (1 / std::abs(zoomLevel)));;
}

void GLCamera::up()
{
    y += (moveSpeed * (1 / std::abs(zoomLevel)));;
    look_y += (moveSpeed * (1 / std::abs(zoomLevel)));;
}

void GLCamera::down()
{
    y -= (moveSpeed * (1 / std::abs(zoomLevel)));;
    look_y -= (moveSpeed * (1 / std::abs(zoomLevel)));;
}

void GLCamera::move(int dx, int dy)
{
    // TODO : Need good scrolling
//    x -= (dx * (0.10 * (1.0 / std::fabs(zoomLevel))));
//    look_x -= (dx * (0.10 * (1.0 / std::fabs(zoomLevel))));
//    y += (dy * (0.10 * (1.0 / std::fabs(zoomLevel))));
//    look_y += (dy * (0.10 * (1.0 / std::fabs(zoomLevel))));

    double glViewWidth = planeRight - planeLeft;
    double glViewHeight = planeTop - planeBottom;

    x -= ((double(dx) / double(canvasWidth)) * glViewWidth);
    look_x -= ((double(dx) / double(canvasWidth)) * glViewWidth);
    y += ((double(dy) / double(canvasWidth)) * glViewHeight);
    look_y += ((double(dy) / double(canvasWidth)) * glViewHeight);
}

void GLCamera::zoomIn()
{
    if(zoomLevel == 121)
        return;

    if(planeRight - planeLeft <= 0.1 || planeTop - planeBottom <= 0.1)
        return;

    zoomLevel += 1;

    planeLeft += zoomSpeed;
    planeRight -= zoomSpeed;
    planeBottom += zoomSpeed;
    planeTop -= zoomSpeed;

    setViewingVolume();
}

void GLCamera::zoomOut()
{
    if(zoomLevel == 1)
        return;

    zoomLevel -= 1;

    planeLeft -= zoomSpeed;
    planeRight += zoomSpeed;
    planeBottom -= zoomSpeed;
    planeTop += zoomSpeed;

    setViewingVolume();
}

void GLCamera::setViewingVolume()
{
    glViewport(0, 0, canvasWidth, canvasHeight);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    this->setProjection();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

}

void GLCamera::setProjection()
{
    GLdouble dx = planeRight - planeLeft;
    GLdouble dy = planeTop - planeBottom;

    if(dx >= dy)
    {
        GLdouble dY = dx * canvasHeight / canvasWidth;
        GLdouble yMax = planeBottom + dY;
        glOrtho(planeLeft, planeRight, planeBottom, yMax, planeNear, planeFar);
    }
    else
    {
        GLdouble dX = dy * canvasWidth / canvasHeight;
        GLdouble xMax = planeLeft + dX;
        glOrtho(planeLeft, xMax, planeBottom, planeTop, planeNear, planeFar);
    }
}

void GLCamera::center()
{
    x = 0.0;
    y = 0.0;
    z = 1.0;

    look_x = 0.0;
    look_y = 0.0;
    look_z = 0.0;
}

<commit_msg>Map Scaling Issue Fix<commit_after>#include <cmath>
#include "glcamera.h"

#ifdef __APPLE__
    #include <GLUT/glut.h>
#else
    #include <glut.h>
#endif

#include <QDebug>

GLCamera::GLCamera()
{
    moveSpeed = 10.0;

    x = 0.0;
    y = 0.0;
    z = 1.0;

    look_x = 0.0;
    look_y = 0.0;
    look_z = 0.0;

    zoomLevel = 1.0;
    zoomSpeed = 0.05;

    // lat="46.791803,9" lon="4.427704,7"
    planeLeft = 437.0;
    planeRight = 449.0;

    planeBottom = 4674.0;
    planeTop = 4686.0;

    planeNear = 0.0;
    planeFar = 10.0;

    canvasWidth = 0;
    canvasHeight = 0;
}

void GLCamera::left()
{
    x -= (moveSpeed * (1 / std::abs(zoomLevel)));
    look_x -= (moveSpeed * (1 / std::abs(zoomLevel)));
}

void GLCamera::right()
{
    x += (moveSpeed * (1 / std::abs(zoomLevel)));;
    look_x += (moveSpeed * (1 / std::abs(zoomLevel)));;
}

void GLCamera::up()
{
    y += (moveSpeed * (1 / std::abs(zoomLevel)));;
    look_y += (moveSpeed * (1 / std::abs(zoomLevel)));;
}

void GLCamera::down()
{
    y -= (moveSpeed * (1 / std::abs(zoomLevel)));;
    look_y -= (moveSpeed * (1 / std::abs(zoomLevel)));;
}

void GLCamera::move(int dx, int dy)
{
    GLdouble gldx = planeRight - planeLeft;
    GLdouble gldy = planeTop - planeBottom;
    GLdouble aspect = GLdouble(canvasWidth) / GLdouble(canvasHeight);

    GLdouble xMax = planeRight;
    GLdouble yMax = planeTop;

    GLdouble dX = gldy * GLdouble(canvasWidth) / GLdouble(canvasHeight);
    GLdouble dY = gldx * GLdouble(canvasHeight) / GLdouble(canvasWidth);

    if(aspect >= 1.0)
    {
        xMax = planeLeft + dX;
        yMax = planeBottom + dY;
    }

    double glViewWidth = xMax - planeLeft;
    //double glViewHeight = yMax - planeBottom;

    x -= ((double(dx) / double(canvasWidth)) * glViewWidth);
    look_x -= ((double(dx) / double(canvasWidth)) * glViewWidth);
    y += ((double(dy) / double(canvasWidth)) * gldy);
    look_y += ((double(dy) / double(canvasWidth)) * gldy);
}

void GLCamera::zoomIn()
{
    if(zoomLevel == 121)
        return;

    if(planeRight - planeLeft <= 0.1 || planeTop - planeBottom <= 0.1)
        return;

    zoomLevel += 1;

    planeLeft += zoomSpeed;
    planeRight -= zoomSpeed;
    planeBottom += zoomSpeed;
    planeTop -= zoomSpeed;

    setViewingVolume();
}

void GLCamera::zoomOut()
{
    if(zoomLevel == 1)
        return;

    zoomLevel -= 1;

    planeLeft -= zoomSpeed;
    planeRight += zoomSpeed;
    planeBottom -= zoomSpeed;
    planeTop += zoomSpeed;

    setViewingVolume();
}

void GLCamera::setViewingVolume()
{
    glViewport(0, 0, canvasWidth, canvasHeight);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    this->setProjection();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

}

void GLCamera::setProjection()
{
    GLdouble dx = planeRight - planeLeft;
    GLdouble dy = planeTop - planeBottom;
    GLdouble aspect = GLdouble(canvasWidth) / GLdouble(canvasHeight);

    //    GLdouble dx = xMax - xOrg;
    //	GLdouble dy = yMax - yOrg;
    //	double aspect_ratio;
    //	if(fabs(dx) > 0.001 || fabs(dy) > 0.001)//Controls how far you can zoom in
    //	{
    //		if(dx >= dy)
    //		{

    //			GLdouble dY = dx * m_height / m_width;
    //			GLdouble yMax = yOrg  + dY;
    //			::glOrtho( xOrg, xMax, yOrg, yMax, -zMax, zMax);
    //		}
    //		else
    //		{
    //			GLdouble dX = dy * m_width / m_height;
    //			GLdouble xMax = xOrg + dX;
    //			::glOrtho( xOrg, xMax, yOrg, yMax, -zMax, zMax);
    //        }

    GLdouble xMax = planeRight;
    GLdouble yMax = planeTop;

    GLdouble dX = dy * GLdouble(canvasWidth) / GLdouble(canvasHeight);
    GLdouble dY = dx * GLdouble(canvasHeight) / GLdouble(canvasWidth);

    if(aspect >= 1.0)
    {
        xMax = planeLeft + dX;
        yMax = planeBottom + dY;
    }

    glOrtho(planeLeft, xMax, planeBottom, yMax, planeNear, planeFar);

//    if(aspect >= 1.0)
//    {
//        GLdouble dY = dx * GLdouble(canvasHeight) / GLdouble(canvasWidth);
//        GLdouble yMax = planeBottom + dY;
////        GLdouble dX = dy * GLdouble(canvasWidth) / GLdouble(canvasHeight);
////        GLdouble xMax = planeLeft + dX;
//        glOrtho(planeLeft, planeRight, planeBottom, yMax, planeNear, planeFar);
//    }
//    else
//    {
//        GLdouble dX = dy * GLdouble(canvasWidth) / GLdouble(canvasHeight);
//        GLdouble xMax = planeLeft + dX;
//        GLdouble dY = dx * GLdouble(canvasHeight) / GLdouble(canvasWidth);
//        GLdouble yMax = planeBottom + dY;
//        glOrtho(planeLeft, xMax, planeBottom, yMax, planeNear, planeFar);
//    }
}

void GLCamera::center()
{
    x = 0.0;
    y = 0.0;
    z = 1.0;

    look_x = 0.0;
    look_y = 0.0;
    look_z = 0.0;
}

<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/RaisePointerReferences.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

namespace {
  // FIXME: This should eventually be parameterized...
  TargetData TD("gccas target");

  cl::opt<std::string>
  InputFilename(cl::Positional, cl::desc("<input llvm assembly>"),cl::Required);

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<int>
  RunNPasses("stopAfterNPasses",
             cl::desc("Only run the first N passes of gccas"), cl::Hidden,
             cl::value_desc("# passes"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));

  cl::opt<std::string>    // Be compatible with what GCC expects
  QOption("Q", cl::desc("Compatibility option (ignored)"),
          cl::Hidden, cl::Prefix);
  cl::opt<bool>
  PrintVersion("V", cl::desc("Print GCCAS version number"), cl::Hidden);
}

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  } else {
    delete P;             // We don't want this pass to run, just delete it now
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions
  addPass(PM, createGlobalDCEPass());            // Kill unused uinit g-vars
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
  addPass(PM, createVerifierPass());             // Verify that input is correct
  addPass(PM, createDeadInstEliminationPass());  // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createIndVarSimplifyPass());       // Simplify indvars
  addPass(PM, createRaisePointerReferencesPass(TD));// Recover type information
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createPromoteMemoryToRegister());  // Promote alloca's to regs
  addPass(PM, createReassociatePass());          // Reassociate expressions
  //addPass(PM, createCorrelatedExpressionEliminationPass());// Kill corr branches
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  if (OutputFilename == "") {   // Didn't specify an output filename?
    std::string IFN = InputFilename;
    int Len = IFN.length();
    if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
      OutputFilename = std::string(IFN.begin(), IFN.end()-2);
    } else {
      OutputFilename = IFN;   // Append a .o to it
    }
    OutputFilename += ".o";
  }

  std::ofstream Out(OutputFilename.c_str(), std::ios::out);
  if (!Out.good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
  RemoveFileOnSignal(OutputFilename);

  if (PrintVersion)
    std::cerr << "LLVM GCCAS version xx\n";  /* For GNU compatibility */

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(&Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());
  return 0;
}
<commit_msg>Improve compatibility with system AS further by allowing input from stdin<commit_after>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/RaisePointerReferences.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

namespace {
  // FIXME: This should eventually be parameterized...
  TargetData TD("gccas target");

  cl::opt<std::string>
  InputFilename(cl::Positional,cl::desc("<input llvm assembly>"),cl::init("-"));

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<int>
  RunNPasses("stopAfterNPasses",
             cl::desc("Only run the first N passes of gccas"), cl::Hidden,
             cl::value_desc("# passes"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));

  cl::opt<std::string>    // Be compatible with what GCC expects
  QOption("Q", cl::desc("Compatibility option (ignored)"),
          cl::Hidden, cl::Prefix);
  cl::opt<bool>
  PrintVersion("V", cl::desc("Print GCCAS version number"), cl::Hidden);
}

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  } else {
    delete P;             // We don't want this pass to run, just delete it now
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions
  addPass(PM, createGlobalDCEPass());            // Kill unused uinit g-vars
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
  addPass(PM, createVerifierPass());             // Verify that input is correct
  addPass(PM, createDeadInstEliminationPass());  // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createIndVarSimplifyPass());       // Simplify indvars
  addPass(PM, createRaisePointerReferencesPass(TD));// Recover type information
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createPromoteMemoryToRegister());  // Promote alloca's to regs
  addPass(PM, createReassociatePass());          // Reassociate expressions
  //addPass(PM, createCorrelatedExpressionEliminationPass());// Kill corr branches
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  std::ostream *Out = 0;
  if (OutputFilename == "") {   // Didn't specify an output filename?
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      std::string IFN = InputFilename;
      int Len = IFN.length();
      if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
        OutputFilename = std::string(IFN.begin(), IFN.end()-2);
      } else {
        OutputFilename = IFN;   // Append a .o to it
      }
      OutputFilename += ".o";
    }
  }

  if (OutputFilename == "-")
    Out = &std::cout;
  else {
    Out = new std::ofstream(OutputFilename.c_str(), std::ios::out);

    // Make sure that the Out file gets unlink'd from the disk if we get a
    // signal
    RemoveFileOnSignal(OutputFilename);
  }

  if (!Out->good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  if (PrintVersion)  /* For GNU compatibility */
    std::cerr << "LLVM GCCAS version xx\n" << std::flush;

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());

  if (Out != &std::cout) delete Out;
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS fwkq1 (1.1.2); FILE ADDED 2003/07/14 16:11:53 mba 1.1.2.1: #110843#: get rid of factories<commit_after><|endoftext|>


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

#include "opencv2/core/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
    std::string in;
    if (argc != 2)
    {
        std::cout << "Usage: lsd_lines [input image]. Now loading building.jpg" << std::endl;
        in = "building.jpg";
    }
    else
    {
        in = argv[1];
    }

    Mat image = imread(in, IMREAD_GRAYSCALE);

#if 0
    Canny(image, image, 50, 200, 3); // Apply canny edge
#endif

    // Create and LSD detector with standard or no refinement.
#if 1
    Ptr<LineSegmentDetector> ls = createLineSegmentDetectorPtr(LSD_REFINE_STD);
#else
    Ptr<LineSegmentDetector> ls = createLineSegmentDetectorPtr(LSD_REFINE_NONE);
#endif

    double start = double(getTickCount());
    vector<Vec4i> lines_std;

    // Detect the lines
    ls->detect(image, lines_std);

    double duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();
    std::cout << "It took " << duration_ms << " ms." << std::endl;

    // Show found lines
    Mat drawnLines(image);
    lsd_std->drawSegments(drawnLines, lines_std);
    imshow("Standard refinement", drawnLines);

    waitKey();
    return 0;
}
<commit_msg>The accurate LineSegmentDetector object.<commit_after>#include <iostream>
#include <string>

#include "opencv2/core/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
    std::string in;
    if (argc != 2)
    {
        std::cout << "Usage: lsd_lines [input image]. Now loading building.jpg" << std::endl;
        in = "building.jpg";
    }
    else
    {
        in = argv[1];
    }

    Mat image = imread(in, IMREAD_GRAYSCALE);

#if 0
    Canny(image, image, 50, 200, 3); // Apply canny edge
#endif

    // Create and LSD detector with standard or no refinement.
#if 1
    Ptr<LineSegmentDetector> ls = createLineSegmentDetectorPtr(LSD_REFINE_STD);
#else
    Ptr<LineSegmentDetector> ls = createLineSegmentDetectorPtr(LSD_REFINE_NONE);
#endif

    double start = double(getTickCount());
    vector<Vec4i> lines_std;

    // Detect the lines
    ls->detect(image, lines_std);

    double duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();
    std::cout << "It took " << duration_ms << " ms." << std::endl;

    // Show found lines
    Mat drawnLines(image);
    ls->drawSegments(drawnLines, lines_std);
    imshow("Standard refinement", drawnLines);

    waitKey();
    return 0;
}
<|endoftext|>


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

#include <assert.h>

// Disable exception handler warnings.
#pragma warning( disable : 4530 )

#include <fstream>

#include "common/windows/string_utils-inl.h"

#include "common/windows/http_upload.h"

namespace google_breakpad {

using std::ifstream;
using std::ios;

static const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)";

// Helper class which closes an internet handle when it goes away
class HTTPUpload::AutoInternetHandle {
 public:
  explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
  ~AutoInternetHandle() {
    if (handle_) {
      InternetCloseHandle(handle_);
    }
  }

  HINTERNET get() { return handle_; }

 private:
  HINTERNET handle_;
};

// static
bool HTTPUpload::SendRequest(const wstring &url,
                             const map<wstring, wstring> &parameters,
                             const wstring &upload_file,
                             const wstring &file_part_name,
                             wstring *response_body,
                             int *response_code) {
  if (response_code) {
    *response_code = 0;
  }

  // TODO(bryner): support non-ASCII parameter names
  if (!CheckParameters(parameters)) {
    return false;
  }

  // Break up the URL and make sure we can handle it
  wchar_t scheme[16], host[256], path[256];
  URL_COMPONENTS components;
  memset(&components, 0, sizeof(components));
  components.dwStructSize = sizeof(components);
  components.lpszScheme = scheme;
  components.dwSchemeLength = sizeof(scheme);
  components.lpszHostName = host;
  components.dwHostNameLength = sizeof(host);
  components.lpszUrlPath = path;
  components.dwUrlPathLength = sizeof(path);
  if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
                        0, &components)) {
    return false;
  }
  bool secure = false;
  if (wcscmp(scheme, L"https") == 0) {
    secure = true;
  } else if (wcscmp(scheme, L"http") != 0) {
    return false;
  }

  AutoInternetHandle internet(InternetOpen(kUserAgent,
                                           INTERNET_OPEN_TYPE_PRECONFIG,
                                           NULL,  // proxy name
                                           NULL,  // proxy bypass
                                           0));   // flags
  if (!internet.get()) {
    return false;
  }

  AutoInternetHandle connection(InternetConnect(internet.get(),
                                                host,
                                                components.nPort,
                                                NULL,    // user name
                                                NULL,    // password
                                                INTERNET_SERVICE_HTTP,
                                                0,       // flags
                                                NULL));  // context
  if (!connection.get()) {
    return false;
  }

  DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0;
  AutoInternetHandle request(HttpOpenRequest(connection.get(),
                                             L"POST",
                                             path,
                                             NULL,    // version
                                             NULL,    // referer
                                             NULL,    // agent type
                                             http_open_flags,
                                             NULL));  // context
  if (!request.get()) {
    return false;
  }

  wstring boundary = GenerateMultipartBoundary();
  wstring content_type_header = GenerateRequestHeader(boundary);
  HttpAddRequestHeaders(request.get(),
                        content_type_header.c_str(),
                        -1, HTTP_ADDREQ_FLAG_ADD);

  string request_body;
  if (!GenerateRequestBody(parameters, upload_file,
                           file_part_name, boundary, &request_body)) {
    return false;
  }

  if (!HttpSendRequest(request.get(), NULL, 0,
                       const_cast<char *>(request_body.data()),
                       static_cast<DWORD>(request_body.size()))) {
    return false;
  }

  // The server indicates a successful upload with HTTP status 200.
  wchar_t http_status[4];
  DWORD http_status_size = sizeof(http_status);
  if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE,
                     static_cast<LPVOID>(&http_status), &http_status_size,
                     0)) {
    return false;
  }

  int http_response = wcstol(http_status, NULL, 10);
  if (response_code) {
    *response_code = http_response;
  }

  bool result = (http_response == 200);

  if (result) {
    result = ReadResponse(request.get(), response_body);
  }

  return result;
}

// static
bool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) {
  bool has_content_length_header = false;
  wchar_t content_length[32];
  DWORD content_length_size = sizeof(content_length);
  DWORD claimed_size;
  string response_body;

  if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH,
                    static_cast<LPVOID>(&content_length),
                    &content_length_size, 0)) {
    has_content_length_header = true;
    claimed_size = wcstol(content_length, NULL, 10);
    response_body.reserve(claimed_size);
  }

  DWORD bytes_available;
  DWORD total_read = 0;
  bool return_code;

  while ((return_code = InternetQueryDataAvailable(request, &bytes_available,
                                                   0, 0) != 0) &&
          bytes_available > 0) {
    vector<char> response_buffer(bytes_available);
    DWORD size_read;

    if ((return_code = InternetReadFile(request, &response_buffer[0],
                                        bytes_available, &size_read) != 0) &&
        size_read > 0) {
      total_read += size_read;
      response_body.append(&response_buffer[0], size_read);
    } else {
      break;
    }
  }

  bool succeeded = return_code && (!has_content_length_header ||
                                   (total_read == claimed_size));
  if (succeeded && response) {
    *response = UTF8ToWide(response_body);
  }

  return succeeded;
}

// static
wstring HTTPUpload::GenerateMultipartBoundary() {
  // The boundary has 27 '-' characters followed by 16 hex digits
  static const wchar_t kBoundaryPrefix[] = L"---------------------------";
  static const int kBoundaryLength = 27 + 16 + 1;

  // Generate some random numbers to fill out the boundary
  int r0 = rand();
  int r1 = rand();

  wchar_t temp[kBoundaryLength];
  swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);

  // remove when VC++7.1 is no longer supported
  temp[kBoundaryLength - 1] = L'\0';

  return wstring(temp);
}

// static
wstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) {
  wstring header = L"Content-Type: multipart/form-data; boundary=";
  header += boundary;
  return header;
}

// static
bool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> &parameters,
                                     const wstring &upload_file,
                                     const wstring &file_part_name,
                                     const wstring &boundary,
                                     string *request_body) {
  vector<char> contents;
  GetFileContents(upload_file, &contents);
  if (contents.empty()) {
    return false;
  }

  string boundary_str = WideToUTF8(boundary);
  if (boundary_str.empty()) {
    return false;
  }

  request_body->clear();

  // Append each of the parameter pairs as a form-data part
  for (map<wstring, wstring>::const_iterator pos = parameters.begin();
       pos != parameters.end(); ++pos) {
    request_body->append("--" + boundary_str + "\r\n");
    request_body->append("Content-Disposition: form-data; name=\"" +
                         WideToUTF8(pos->first) + "\"\r\n\r\n" +
                         WideToUTF8(pos->second) + "\r\n");
  }

  // Now append the upload file as a binary (octet-stream) part
  string filename_utf8 = WideToUTF8(upload_file);
  if (filename_utf8.empty()) {
    return false;
  }

  string file_part_name_utf8 = WideToUTF8(file_part_name);
  if (file_part_name_utf8.empty()) {
    return false;
  }

  request_body->append("--" + boundary_str + "\r\n");
  request_body->append("Content-Disposition: form-data; "
                       "name=\"" + file_part_name_utf8 + "\"; "
                       "filename=\"" + filename_utf8 + "\"\r\n");
  request_body->append("Content-Type: application/octet-stream\r\n");
  request_body->append("\r\n");

  if (!contents.empty()) {
      request_body->append(&(contents[0]), contents.size());
  }
  request_body->append("\r\n");
  request_body->append("--" + boundary_str + "--\r\n");
  return true;
}

// static
void HTTPUpload::GetFileContents(const wstring &filename,
                                 vector<char> *contents) {
  // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a
  // wchar_t* filename, so use _wfopen directly in that case.  For VC8 and
  // later, _wfopen has been deprecated in favor of _wfopen_s, which does
  // not exist in earlier versions, so let the ifstream open the file itself.
#if _MSC_VER >= 1400  // MSVC 2005/8
  ifstream file;
  file.open(filename.c_str(), ios::binary);
#else  // _MSC_VER >= 1400
  ifstream file(_wfopen(filename.c_str(), L"rb"));
#endif  // _MSC_VER >= 1400
  if (file.is_open()) {
    file.seekg(0, ios::end);
    int length = file.tellg();
    contents->resize(length);
    if (length != 0) {
        file.seekg(0, ios::beg);
        file.read(&((*contents)[0]), length);
    }
    file.close();
  } else {
    contents->clear();
  }
}

// static
wstring HTTPUpload::UTF8ToWide(const string &utf8) {
  if (utf8.length() == 0) {
    return wstring();
  }

  // compute the length of the buffer we'll need
  int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);

  if (charcount == 0) {
    return wstring();
  }

  // convert
  wchar_t* buf = new wchar_t[charcount];
  MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount);
  wstring result(buf);
  delete[] buf;
  return result;
}

// static
string HTTPUpload::WideToUTF8(const wstring &wide) {
  if (wide.length() == 0) {
    return string();
  }

  // compute the length of the buffer we'll need
  int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1,
                                      NULL, 0, NULL, NULL);
  if (charcount == 0) {
    return string();
  }

  // convert
  char *buf = new char[charcount];
  WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount,
                      NULL, NULL);

  string result(buf);
  delete[] buf;
  return result;
}

// static
bool HTTPUpload::CheckParameters(const map<wstring, wstring> &parameters) {
  for (map<wstring, wstring>::const_iterator pos = parameters.begin();
       pos != parameters.end(); ++pos) {
    const wstring &str = pos->first;
    if (str.size() == 0) {
      return false;  // disallow empty parameter names
    }
    for (unsigned int i = 0; i < str.size(); ++i) {
      wchar_t c = str[i];
      if (c < 32 || c == '"' || c > 127) {
        return false;
      }
    }
  }
  return true;
}

}  // namespace google_breakpad
<commit_msg>Silences warning C4701: local variable 'claimed_size' may be used with out having been initialized.  The code is correct however the compiler can't see the relationship between has_content_length_header and the claimed_size so it generates a warning.<commit_after>// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <assert.h>

// Disable exception handler warnings.
#pragma warning( disable : 4530 )

#include <fstream>

#include "common/windows/string_utils-inl.h"

#include "common/windows/http_upload.h"

namespace google_breakpad {

using std::ifstream;
using std::ios;

static const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)";

// Helper class which closes an internet handle when it goes away
class HTTPUpload::AutoInternetHandle {
 public:
  explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
  ~AutoInternetHandle() {
    if (handle_) {
      InternetCloseHandle(handle_);
    }
  }

  HINTERNET get() { return handle_; }

 private:
  HINTERNET handle_;
};

// static
bool HTTPUpload::SendRequest(const wstring &url,
                             const map<wstring, wstring> &parameters,
                             const wstring &upload_file,
                             const wstring &file_part_name,
                             wstring *response_body,
                             int *response_code) {
  if (response_code) {
    *response_code = 0;
  }

  // TODO(bryner): support non-ASCII parameter names
  if (!CheckParameters(parameters)) {
    return false;
  }

  // Break up the URL and make sure we can handle it
  wchar_t scheme[16], host[256], path[256];
  URL_COMPONENTS components;
  memset(&components, 0, sizeof(components));
  components.dwStructSize = sizeof(components);
  components.lpszScheme = scheme;
  components.dwSchemeLength = sizeof(scheme);
  components.lpszHostName = host;
  components.dwHostNameLength = sizeof(host);
  components.lpszUrlPath = path;
  components.dwUrlPathLength = sizeof(path);
  if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
                        0, &components)) {
    return false;
  }
  bool secure = false;
  if (wcscmp(scheme, L"https") == 0) {
    secure = true;
  } else if (wcscmp(scheme, L"http") != 0) {
    return false;
  }

  AutoInternetHandle internet(InternetOpen(kUserAgent,
                                           INTERNET_OPEN_TYPE_PRECONFIG,
                                           NULL,  // proxy name
                                           NULL,  // proxy bypass
                                           0));   // flags
  if (!internet.get()) {
    return false;
  }

  AutoInternetHandle connection(InternetConnect(internet.get(),
                                                host,
                                                components.nPort,
                                                NULL,    // user name
                                                NULL,    // password
                                                INTERNET_SERVICE_HTTP,
                                                0,       // flags
                                                NULL));  // context
  if (!connection.get()) {
    return false;
  }

  DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0;
  AutoInternetHandle request(HttpOpenRequest(connection.get(),
                                             L"POST",
                                             path,
                                             NULL,    // version
                                             NULL,    // referer
                                             NULL,    // agent type
                                             http_open_flags,
                                             NULL));  // context
  if (!request.get()) {
    return false;
  }

  wstring boundary = GenerateMultipartBoundary();
  wstring content_type_header = GenerateRequestHeader(boundary);
  HttpAddRequestHeaders(request.get(),
                        content_type_header.c_str(),
                        -1, HTTP_ADDREQ_FLAG_ADD);

  string request_body;
  if (!GenerateRequestBody(parameters, upload_file,
                           file_part_name, boundary, &request_body)) {
    return false;
  }

  if (!HttpSendRequest(request.get(), NULL, 0,
                       const_cast<char *>(request_body.data()),
                       static_cast<DWORD>(request_body.size()))) {
    return false;
  }

  // The server indicates a successful upload with HTTP status 200.
  wchar_t http_status[4];
  DWORD http_status_size = sizeof(http_status);
  if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE,
                     static_cast<LPVOID>(&http_status), &http_status_size,
                     0)) {
    return false;
  }

  int http_response = wcstol(http_status, NULL, 10);
  if (response_code) {
    *response_code = http_response;
  }

  bool result = (http_response == 200);

  if (result) {
    result = ReadResponse(request.get(), response_body);
  }

  return result;
}

// static
bool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) {
  bool has_content_length_header = false;
  wchar_t content_length[32];
  DWORD content_length_size = sizeof(content_length);
  DWORD claimed_size = 0;
  string response_body;

  if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH,
                    static_cast<LPVOID>(&content_length),
                    &content_length_size, 0)) {
    has_content_length_header = true;
    claimed_size = wcstol(content_length, NULL, 10);
    response_body.reserve(claimed_size);
  }

  DWORD bytes_available;
  DWORD total_read = 0;
  bool return_code;

  while ((return_code = InternetQueryDataAvailable(request, &bytes_available,
                                                   0, 0) != 0) &&
          bytes_available > 0) {
    vector<char> response_buffer(bytes_available);
    DWORD size_read;

    if ((return_code = InternetReadFile(request, &response_buffer[0],
                                        bytes_available, &size_read) != 0) &&
        size_read > 0) {
      total_read += size_read;
      response_body.append(&response_buffer[0], size_read);
    } else {
      break;
    }
  }

  bool succeeded = return_code && (!has_content_length_header ||
                                   (total_read == claimed_size));
  if (succeeded && response) {
    *response = UTF8ToWide(response_body);
  }

  return succeeded;
}

// static
wstring HTTPUpload::GenerateMultipartBoundary() {
  // The boundary has 27 '-' characters followed by 16 hex digits
  static const wchar_t kBoundaryPrefix[] = L"---------------------------";
  static const int kBoundaryLength = 27 + 16 + 1;

  // Generate some random numbers to fill out the boundary
  int r0 = rand();
  int r1 = rand();

  wchar_t temp[kBoundaryLength];
  swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);

  // remove when VC++7.1 is no longer supported
  temp[kBoundaryLength - 1] = L'\0';

  return wstring(temp);
}

// static
wstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) {
  wstring header = L"Content-Type: multipart/form-data; boundary=";
  header += boundary;
  return header;
}

// static
bool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> &parameters,
                                     const wstring &upload_file,
                                     const wstring &file_part_name,
                                     const wstring &boundary,
                                     string *request_body) {
  vector<char> contents;
  GetFileContents(upload_file, &contents);
  if (contents.empty()) {
    return false;
  }

  string boundary_str = WideToUTF8(boundary);
  if (boundary_str.empty()) {
    return false;
  }

  request_body->clear();

  // Append each of the parameter pairs as a form-data part
  for (map<wstring, wstring>::const_iterator pos = parameters.begin();
       pos != parameters.end(); ++pos) {
    request_body->append("--" + boundary_str + "\r\n");
    request_body->append("Content-Disposition: form-data; name=\"" +
                         WideToUTF8(pos->first) + "\"\r\n\r\n" +
                         WideToUTF8(pos->second) + "\r\n");
  }

  // Now append the upload file as a binary (octet-stream) part
  string filename_utf8 = WideToUTF8(upload_file);
  if (filename_utf8.empty()) {
    return false;
  }

  string file_part_name_utf8 = WideToUTF8(file_part_name);
  if (file_part_name_utf8.empty()) {
    return false;
  }

  request_body->append("--" + boundary_str + "\r\n");
  request_body->append("Content-Disposition: form-data; "
                       "name=\"" + file_part_name_utf8 + "\"; "
                       "filename=\"" + filename_utf8 + "\"\r\n");
  request_body->append("Content-Type: application/octet-stream\r\n");
  request_body->append("\r\n");

  if (!contents.empty()) {
      request_body->append(&(contents[0]), contents.size());
  }
  request_body->append("\r\n");
  request_body->append("--" + boundary_str + "--\r\n");
  return true;
}

// static
void HTTPUpload::GetFileContents(const wstring &filename,
                                 vector<char> *contents) {
  // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a
  // wchar_t* filename, so use _wfopen directly in that case.  For VC8 and
  // later, _wfopen has been deprecated in favor of _wfopen_s, which does
  // not exist in earlier versions, so let the ifstream open the file itself.
#if _MSC_VER >= 1400  // MSVC 2005/8
  ifstream file;
  file.open(filename.c_str(), ios::binary);
#else  // _MSC_VER >= 1400
  ifstream file(_wfopen(filename.c_str(), L"rb"));
#endif  // _MSC_VER >= 1400
  if (file.is_open()) {
    file.seekg(0, ios::end);
    int length = file.tellg();
    contents->resize(length);
    if (length != 0) {
        file.seekg(0, ios::beg);
        file.read(&((*contents)[0]), length);
    }
    file.close();
  } else {
    contents->clear();
  }
}

// static
wstring HTTPUpload::UTF8ToWide(const string &utf8) {
  if (utf8.length() == 0) {
    return wstring();
  }

  // compute the length of the buffer we'll need
  int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);

  if (charcount == 0) {
    return wstring();
  }

  // convert
  wchar_t* buf = new wchar_t[charcount];
  MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount);
  wstring result(buf);
  delete[] buf;
  return result;
}

// static
string HTTPUpload::WideToUTF8(const wstring &wide) {
  if (wide.length() == 0) {
    return string();
  }

  // compute the length of the buffer we'll need
  int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1,
                                      NULL, 0, NULL, NULL);
  if (charcount == 0) {
    return string();
  }

  // convert
  char *buf = new char[charcount];
  WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount,
                      NULL, NULL);

  string result(buf);
  delete[] buf;
  return result;
}

// static
bool HTTPUpload::CheckParameters(const map<wstring, wstring> &parameters) {
  for (map<wstring, wstring>::const_iterator pos = parameters.begin();
       pos != parameters.end(); ++pos) {
    const wstring &str = pos->first;
    if (str.size() == 0) {
      return false;  // disallow empty parameter names
    }
    for (unsigned int i = 0; i < str.size(); ++i) {
      wchar_t c = str[i];
      if (c < 32 || c == '"' || c > 127) {
        return false;
      }
    }
  }
  return true;
}

}  // namespace google_breakpad
<|endoftext|>