<commit_before>// some backup code

        class LambdaRankObj_NDCG : public LambdaRankObj{

            static inline float CalcDCG(const std::vector< float > &rec) {
                double sumdcg = 0.0;
                for (size_t i = 0; i < rec.size(); i++){
                    const unsigned rel = static_cast<unsigned>(rec[i]);
                    if (rel != 0){
                        sumdcg += logf(2.0f) *((1 << rel) - 1) / logf(i + 2);
                    }
                }
                return static_cast<float>(sumdcg);
            }

            /*
            * \brief Obtain the delta NDCG if trying to switch the positions of instances in index1 or index2
            *        in sorted triples. Here DCG is calculated as sigma_i 2^rel_i/log(i + 1)
            * \param sorted_triple the fields are predition,label,original index
            * \param index1,index2 the instances switched
            * \param the IDCG of the list
            */
            inline float GetLambdaNDCG(const std::vector< Triple > sorted_triple,
            int index1,
            int index2, float IDCG){
                double original = (1 << static_cast<int>(sorted_triple[index1].label_)) / log(index1 + 2)
                    + (1 << static_cast<int>(sorted_triple[index2].label_)) / log(index2 + 2);
                double changed = (1 << static_cast<int>(sorted_triple[index2].label_)) / log(index1 + 2)
                    + (1 << static_cast<int>(sorted_triple[index1].label_)) / log(index2 + 2);
                double ans = (original - changed) / IDCG;
                if (ans < 0) ans = -ans;
                return static_cast<float>(ans);
            }

            inline float GetIDCG(const std::vector< Triple > sorted_triple){
                std::vector<float> labels;
                for (size_t i = 0; i < sorted_triple.size(); i++){
                    labels.push_back(sorted_triple[i].label_);
                }

                std::sort(labels.begin(), labels.end(), std::greater<float>());
                return CalcDCG(labels);
            }

            inline void GetLambda(const std::vector<float> &preds,
            const std::vector<float> &labels,
            const std::vector<unsigned> &group_index,
            const std::vector< std::pair<int, int> > &pairs, std::vector<float> &lambda, int group){
                std::vector< Triple > sorted_triple;
                std::vector<int> index_remap;
                float IDCG;

                GetSortedTuple(preds, labels, group_index, group, sorted_triple);
                GetIndexMap(sorted_triple, group_index[group], index_remap);
                IDCG = GetIDCG(sorted_triple);

                lambda.resize(pairs.size());
                for (size_t i = 0; i < pairs.size(); i++){
                    lambda[i] = GetLambdaNDCG(sorted_triple,
                        index_remap[pairs[i].first],index_remap[pairs[i].second],IDCG);
                }
            }
        };

        class LambdaRankObj_MAP : public LambdaRankObj{
            class Quadruple{
            public:
                /* \brief the accumulated precision */
                float ap_acc_;
                /* \brief the accumulated precision assuming a positive instance is missing*/
                float ap_acc_miss_;
                /* \brief the accumulated precision assuming that one more positive instance is inserted ahead*/
                float ap_acc_add_;
                /* \brief the accumulated positive instance count */
                float hits_;

                Quadruple(){}

                Quadruple(const Quadruple& q){
                    ap_acc_ = q.ap_acc_;
                    ap_acc_miss_ = q.ap_acc_miss_;
                    ap_acc_add_ = q.ap_acc_add_;
                    hits_ = q.hits_;
                }

                Quadruple(float ap_acc, float ap_acc_miss, float ap_acc_add, float hits
                    ) :ap_acc_(ap_acc), ap_acc_miss_(ap_acc_miss), ap_acc_add_(ap_acc_add), hits_(hits){

                }

            };

            /*
            * \brief Obtain the delta MAP if trying to switch the positions of instances in index1 or index2
            *        in sorted triples
            * \param sorted_triple the fields are predition,label,original index
            * \param index1,index2 the instances switched
            * \param map_acc a vector containing the accumulated precisions for each position in a list
            */
            inline float GetLambdaMAP(const std::vector< Triple > sorted_triple,
            int index1, int index2,
            std::vector< Quadruple > &map_acc){
                if (index1 == index2 || sorted_triple[index1].label_ == sorted_triple[index2].label_) return 0.0;
                if (index1 > index2) std::swap(index1, index2);
                float original = map_acc[index2].ap_acc_; // The accumulated precision in the interval [index1,index2]
                if (index1 != 0) original -= map_acc[index1 - 1].ap_acc_;
                float changed = 0;
                if (sorted_triple[index1].label_ < sorted_triple[index2].label_){
                    changed += map_acc[index2 - 1].ap_acc_add_ - map_acc[index1].ap_acc_add_;
                    changed += (map_acc[index1].hits_ + 1.0f) / (index1 + 1);
                }
                else{
                    changed += map_acc[index2 - 1].ap_acc_miss_ - map_acc[index1].ap_acc_miss_;
                    changed += map_acc[index2].hits_ / (index2 + 1);
                }
                float ans = (changed - original) / (map_acc[map_acc.size() - 1].hits_);
                if (ans < 0) ans = -ans;
                return ans;
            }

            /*
            * \brief preprocessing results for calculating delta MAP
            * \return The first field is the accumulated precision, the second field is the
            *         accumulated precision assuming a positive instance is missing,
            *         the third field is the accumulated precision assuming that one more positive
            *         instance is inserted, the fourth field is the accumulated positive instance count
            */
            inline void GetMAPAcc(const std::vector< Triple > sorted_triple,
                std::vector< Quadruple > &map_acc){
                map_acc.resize(sorted_triple.size());
                float hit = 0, acc1 = 0, acc2 = 0, acc3 = 0;
                for (size_t i = 1; i <= sorted_triple.size(); i++){
                    if ((int)sorted_triple[i - 1].label_ == 1) {
                        hit++;
                        acc1 += hit / i;
                        acc2 += (hit - 1) / i;
                        acc3 += (hit + 1) / i;
                    }
                    map_acc[i-1] = Quadruple(acc1, acc2, acc3, hit);
                }
            }

            inline void GetLambda(const std::vector<float> &preds,
                                  const std::vector<float> &labels,
                                  const std::vector<unsigned> &group_index,
                                  const std::vector< std::pair<int, int> > &pairs, std::vector<float> &lambda, int group){
                std::vector< Triple > sorted_triple;
                std::vector<int> index_remap;
                std::vector< Quadruple > map_acc;

                GetSortedTuple(preds, labels, group_index, group, sorted_triple);
                GetIndexMap(sorted_triple, group_index[group], index_remap);
                GetMAPAcc(sorted_triple, map_acc);

                lambda.resize(pairs.size());
                for (size_t i = 0; i < pairs.size(); i++){
                    lambda[i] = GetLambdaMAP(sorted_triple,
                        index_remap[pairs[i].first], index_remap[pairs[i].second], map_acc);
                }
            }
        };

<commit_msg>pre-release version<commit_after><|endoftext|>


<commit_before> /***************************************************************************
 *            test_stack.cpp
 *
 *  Thu May  1 22:02:00 2003
 *  Copyright  2003  Roman Dementiev
 *  dementiev@mpi-sb.mpg.de
 ****************************************************************************/

#include "stack.h"

//! \example test_stack.cpp
//! This is an example of how to use \c stxxl::STACK_GENERATOR class
//! to generate an \b external stack type
//! with \c stxxl::grow_shrink_stack implementation, \b four blocks per page,
//! block size \b 4096 bytes

using namespace stxxl;

int main(int argc, char * argv[])
{
  typedef STACK_GENERATOR<int,external,grow_shrink,4,4096>::result ext_stack_type;
  typedef STACK_GENERATOR<int,external,grow_shrink2,1,4096>::result ext_stack_type2;

  if(argc<2)
  {
    STXXL_MSG("Usage: "<<argv[0]<<" test_size_in_pages")
    abort();
  }
  {
    ext_stack_type my_stack;
    int test_size = atoi(argv[1])*4*4096/sizeof(int),i;

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    std::stack<int> int_stack;

    for(i = 0; i < test_size;i++)
    {
      int_stack.push(i);
      assert(int_stack.top() == i);
      assert(int(int_stack.size()) == i+1);
    }

    ext_stack_type my_stack1(int_stack);

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack1.top() == i);
      my_stack1.pop();
      assert(my_stack1.size() == i);
    };
    STXXL_MSG("Test 1 passed.")
  }
  {
    prefetch_pool<ext_stack_type2::block_type> p_pool(10);
    write_pool<ext_stack_type2::block_type> w_pool(10);
    ext_stack_type2 my_stack(p_pool,w_pool,0);
    int test_size = atoi(argv[1])*4*4096/sizeof(int),i;

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    STXXL_MSG("Test 2 passed.")
  }

  return 0;
}
<commit_msg>*** empty log message ***<commit_after> /***************************************************************************
 *            test_stack.cpp
 *
 *  Thu May  1 22:02:00 2003
 *  Copyright  2003  Roman Dementiev
 *  dementiev@mpi-sb.mpg.de
 ****************************************************************************/

#include "stack.h"

//! \example test_stack.cpp
//! This is an example of how to use \c stxxl::STACK_GENERATOR class
//! to generate an \b external stack type
//! with \c stxxl::grow_shrink_stack implementation, \b four blocks per page,
//! block size \b 4096 bytes

using namespace stxxl;

int main(int argc, char * argv[])
{
  typedef STACK_GENERATOR<int,external,grow_shrink,4,4096>::result ext_stack_type;
  typedef STACK_GENERATOR<int,external,grow_shrink2,1,4096>::result ext_stack_type2;

  if(argc<2)
  {
    STXXL_MSG("Usage: "<<argv[0]<<" test_size_in_pages")
    abort();
  }
  {
    ext_stack_type my_stack;
    int test_size = atoi(argv[1])*4*4096/sizeof(int),i;

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    std::stack<int> int_stack;

    for(i = 0; i < test_size;i++)
    {
      int_stack.push(i);
      assert(int_stack.top() == i);
      assert(int(int_stack.size()) == i+1);
    }

    ext_stack_type my_stack1(int_stack);

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack1.top() == i);
      my_stack1.pop();
      assert(my_stack1.size() == i);
    };
    STXXL_MSG("Test 1 passed.")
  }
  {
    // prefetch pool with 10 blocks (> D is recommended)
    prefetch_pool<ext_stack_type2::block_type> p_pool(10);
    // write pool with 10 blocks (> D is recommended)
    write_pool<ext_stack_type2::block_type> w_pool(10);
    // create a stack that does not prefetch (level of prefetch agrssiveness 0)
    ext_stack_type2 my_stack(p_pool,w_pool,0);
    int test_size = atoi(argv[1])*4*4096/sizeof(int),i;

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }
    my_stack.set_prefetch_aggr(10);
    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    for(i = 0; i < test_size;i++)
    {
      my_stack.push(i);
      assert(my_stack.top() == i);
      assert(my_stack.size() == i+1);
    }

    for(i=test_size-1;i>=0;i--)
    {
      assert(my_stack.top() == i);
      my_stack.pop();
      assert(my_stack.size() == i);
    };

    STXXL_MSG("Test 2 passed.")
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <pwd.h>
#include <grp.h>
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

bool isDirectory(char* directoryName) {

	struct stat directoryInCurrent;

	if (-1 == (stat(directoryName, &directoryInCurrent))) {

		return false;
	}

	if (directoryInCurrent.st_mode & S_IFDIR) {
		return true;
	}
	else {
		return false;
	}
}

int ls(char* directoryName) {

		char const *dirName = directoryName;
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
			cerr << "Error(" << errno << ") opening " << dirName << endl;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << " ";
			}
		}
		cout << endl;
		closedir(dirp);
		return 0;
}

int lsWithFlags(char* directoryName, vector<string> flags) {

	char const *dirName = directoryName;
	DIR *dirp;
	if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
		return errno;
	}

	bool isA = false;
	bool isL = false;
	bool isR = false;
	for (unsigned i = 0; i < flags.size(); ++i) {
		for (unsigned k = 0; k < flags.at(i).size(); ++k) {
			if (flags.at(i).at(k) == 'a')
				isA = true; // there's an -a flag
			else if (flags.at(i).at(k) == 'l')
				isL = true; // there's an -l flag
			else if (flags.at(i).at(k) == 'R')
				isR = true; // there's an -R flag
		}

	}

	dirent *direntp;
	if (isL) { //run -l flag

		struct stat current;

		struct passwd *x;
		struct group *y;
		while ((direntp = readdir(dirp))) {

			//cout << "direntp: " << direntp->d_name << endl;
			char curdir[1000];
			strcat(curdir, directoryName);
			strcat(curdir, "/");
			strcat(curdir, direntp->d_name);
			strcat(curdir, "/");

			cout << curdir << endl;
			if (-1 == (stat(/*toCur*/curdir, &current))) {

				perror("stat failed");
				return -1;
			}
			if (direntp->d_name[0] == '.' && !isA) // if there's no -a flag, don't print files
															   // starting with .
				continue;
			else {

				if (current.st_mode & S_IFDIR)
					cout << "d";

				if (current.st_mode & S_IFLNK)
					cout << "l";

				if (!(current.st_mode & S_IFDIR) && !(current.st_mode & S_IFLNK))
					cout << "-";

				if (current.st_mode & S_IRUSR)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWUSR)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXUSR)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IRGRP)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWGRP)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXGRP)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IROTH)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWOTH)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXOTH)
					cout << "x";
				else
					cout << "-";

				cout << " ";

				cout << current.st_nlink << " ";

				if ((x = getpwuid(current.st_uid)) != NULL)
					cout << x->pw_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}

				if ((y = getgrgid(current.st_gid)) != NULL)
					cout << y->gr_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}
				cout << current.st_size << " ";

				char buff[20];
				struct tm * timeinfo;
				timeinfo = localtime(&(current.st_mtime));
				strftime(buff, 20, "%b %d %H:%M", timeinfo);
				printf("%s",buff);

				cout << " " << direntp->d_name;
				if (isR)
					lsWithFlags(curdir, flags);
			}
			cout << endl;

		}
		closedir(dirp);

	}

	else if (isA) {
		while ((direntp = readdir(dirp))) {

			//cout << direntp->d_name << endl; // use stat here to find attributes of a file
			printf(direntp->d_name, 8);
			cout << " ";

		}
		closedir(dirp);
	}
	return 0;
}

int main(int argc, char* argv[]) {

	if (argc == 1) {

		if (errno == ls(".")) {

			return errno;
		}
	}

	else {

		vector<string> directories;
		vector<string> flags;
		string toInsert = "./";
		for (int i = 1; i < argc; ++i) {

			if (argv[i][0] == '-') {

				flags.push_back(argv[i]);
			} else {

				directories.push_back(argv[i]);
			}
		}

		for (unsigned i = 0; i < directories.size(); ++i) {

			directories.at(i).insert(0, toInsert);
		}
		if (flags.size() == 0) {

			for (unsigned i = 0; i < directories.size(); ++i) {

				char* directoryName = new char[directories.at(i).size() + 1];
				strcpy(directoryName, directories.at(i).c_str());

				ls(directoryName);

				delete [] directoryName;
			}
		}
		else if (directories.size() == 0) {

			lsWithFlags(".", flags);
		}
		else {
			//cout << "directories: ";
			//for (unsigned i = 0; i < directories.size(); ++i)
				//cout << directories.at(i) << " ";
			//cout << endl;

			if (directories.size() == 1) {

				char* directoryName = new char[directories.at(0).size() + 1];
				strcpy(directoryName, directories.at(0).c_str());

				lsWithFlags(directoryName, flags);

				delete [] directoryName;
			}

			else {
				for (unsigned int i = 0; i < directories.size(); ++i) {
					//cout << 145 << endl;

					char* directoryName = new char[directories.at(i).size() + 1];
					strcpy(directoryName, directories.at(i).c_str());

					lsWithFlags(directoryName, flags);
					delete [] directoryName;
				}
			}
		}
	}

}

<commit_msg>added -l protection functionality<commit_after>#include <pwd.h>
#include <grp.h>
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

bool isDirectory(char* directoryName) {

	struct stat directoryInCurrent;

	if (-1 == (stat(directoryName, &directoryInCurrent))) {

		return false;
	}

	if (directoryInCurrent.st_mode & S_IFDIR) {
		return true;
	}
	else {
		return false;
	}
}

int ls(char* directoryName) {

		char const *dirName = directoryName;
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
			cerr << "Error(" << errno << ") opening " << dirName << endl;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << " ";
			}
		}
		cout << endl;
		closedir(dirp);
		return 0;
}

int lsWithFlags(char* directoryName, vector<string> flags) {

	char const *dirName = directoryName;
	DIR *dirp;
	if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
		return errno;
	}

	bool isA = false;
	bool isL = false;
	bool isR = false;
	for (unsigned i = 0; i < flags.size(); ++i) {
		for (unsigned k = 0; k < flags.at(i).size(); ++k) {
			if (flags.at(i).at(k) == 'a')
				isA = true; // there's an -a flag
			else if (flags.at(i).at(k) == 'l')
				isL = true; // there's an -l flag
			else if (flags.at(i).at(k) == 'R')
				isR = true; // there's an -R flag
		}

	}

	dirent *direntp;
	if (isL) { //run -l flag

		struct stat current;

		struct passwd *x;
		struct group *y;
		while ((direntp = readdir(dirp))) {

			//cout << "direntp: " << direntp->d_name << endl;
			char curdir[1000];
			strcpy(curdir, directoryName);
			strcat(curdir, "/");
			strcat(curdir, direntp->d_name);
			strcat(curdir, "/");

			cout << curdir << endl;
			if (-1 == (stat(/*toCur*/curdir, &current))) {

				perror("stat failed");
				return -1;
			}
			if (direntp->d_name[0] == '.' && !isA) // if there's no -a flag, don't print files
															   // starting with .
				continue;
			else {

				if (current.st_mode & S_IFDIR)
					cout << "d";

				if (current.st_mode & S_IFLNK)
					cout << "l";

				if (!(current.st_mode & S_IFDIR) && !(current.st_mode & S_IFLNK))
					cout << "-";

				if (current.st_mode & S_IRUSR)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWUSR)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXUSR)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IRGRP)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWGRP)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXGRP)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IROTH)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWOTH)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXOTH)
					cout << "x";
				else
					cout << "-";

				cout << " ";

				cout << current.st_nlink << " ";

				if ((x = getpwuid(current.st_uid)) != NULL)
					cout << x->pw_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}

				if ((y = getgrgid(current.st_gid)) != NULL)
					cout << y->gr_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}
				cout << current.st_size << " ";

				char buff[20];
				struct tm * timeinfo;
				timeinfo = localtime(&(current.st_mtime));
				strftime(buff, 20, "%b %d %H:%M", timeinfo);
				printf("%s",buff);

				cout << " " << direntp->d_name;
				if (isR)
					lsWithFlags(curdir, flags);
			}
			cout << endl;

		}
		closedir(dirp);

	}

	else if (isA) {
		while ((direntp = readdir(dirp))) {

			//cout << direntp->d_name << endl; // use stat here to find attributes of a file
			printf(direntp->d_name, 8);
			cout << " ";

		}
		closedir(dirp);
	}
	return 0;
}

int main(int argc, char* argv[]) {

	if (argc == 1) {

		if (errno == ls(".")) {

			return errno;
		}
	}

	else {

		vector<string> directories;
		vector<string> flags;
		string toInsert = "./";
		for (int i = 1; i < argc; ++i) {

			if (argv[i][0] == '-') {

				flags.push_back(argv[i]);
			} else {

				directories.push_back(argv[i]);
			}
		}

		for (unsigned i = 0; i < directories.size(); ++i) {

			directories.at(i).insert(0, toInsert);
		}
		if (flags.size() == 0) {

			for (unsigned i = 0; i < directories.size(); ++i) {

				char* directoryName = new char[directories.at(i).size() + 1];
				strcpy(directoryName, directories.at(i).c_str());

				ls(directoryName);

				delete [] directoryName;
			}
		}
		else if (directories.size() == 0) {

			lsWithFlags(".", flags);
		}
		else {
			//cout << "directories: ";
			//for (unsigned i = 0; i < directories.size(); ++i)
				//cout << directories.at(i) << " ";
			//cout << endl;

			if (directories.size() == 1) {

				char* directoryName = new char[directories.at(0).size() + 1];
				strcpy(directoryName, directories.at(0).c_str());

				lsWithFlags(directoryName, flags);

				delete [] directoryName;
			}

			else {
				for (unsigned int i = 0; i < directories.size(); ++i) {
					//cout << 145 << endl;

					char* directoryName = new char[directories.at(i).size() + 1];
					strcpy(directoryName, directories.at(i).c_str());

					lsWithFlags(directoryName, flags);
					delete [] directoryName;
				}
			}
		}
	}

}

<|endoftext|>


<commit_before>/*
 * Copyright 2016 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/lib/cpp2/fatal/reflection.h>

#include <thrift/lib/cpp2/fatal/demo/gen-cpp2/metrics_fatal_types.h>

#include <folly/Conv.h>
#include <folly/init/Init.h>

#include <fatal/type/cat.h>

#include <iostream>

using namespace apache::thrift;
using namespace static_reflection::demo;

struct metrics_client {
  template <typename Metric, typename Value>
  void add(Metric const &name, Value const &value) {
    metrics_[name] += value;
  }

  void report() {
    for (auto const &i: metrics_) {
      std::cout << i.first << ": " << i.second << '\n';
    }
  }

private:
  std::unordered_map<std::string, std::intmax_t> metrics_;
};

// dynamic //

struct export_metric_dynamic {
  template <typename Member, std::size_t Index, typename T>
  void operator ()(
    fatal::indexed<Member, Index>,
    metrics_client &sink,
    T const &metrics,
    std::string const &prefix
  ) const {
    auto const key = prefix + fatal::z_data<typename Member::name>();
    auto const &value = Member::getter::ref(metrics);

    sink.add(key, value);
  }
};

std::string const kPrefix = "my_app.";

template <typename T>
void export_metrics_dynamic(metrics_client &sink, T const &metrics) {
  using info = reflect_struct<T>;

  fatal::foreach<typename info::members>(
    export_metric_dynamic(),
    sink,
    metrics,
    folly::to<std::string>(kPrefix, fatal::z_data<typename info::name>(), '.')
  );
}

// static //

struct export_metric_static {
  FATAL_S(prefix, "my_app");
  FATAL_S(dot, ".");

  template <typename Member, std::size_t Index, typename T>
  void operator ()(
    fatal::indexed<Member, Index>,
    metrics_client &sink,
    T const &metrics
  ) const {
    using info = reflect_struct<T>;
    using key = fatal::cat<
      prefix,
      dot,
      typename info::name,
      dot,
      typename Member::name
    >;

    auto const &value = Member::getter::ref(metrics);
    sink.add(fatal::z_data<key>(), value);
  }
};

template <typename T>
void export_metrics_static(metrics_client &sink, T const &metrics) {
  fatal::foreach<typename reflect_struct<T>::members>(
    export_metric_static(),
    sink,
    metrics
  );
}

// driver //

int main(int argc, char **argv) {
  folly::init(&argc, &argv);

  metrics_client sink;

  host_info metric;
  metric.cpu = 1;
  metric.memory = 12;
  metric.disk = 1234;
  metric.network_bytes_sent = 123;
  metric.network_bytes_received = 321;
  metric.network_retransmits = 2;
  metric.network_connection_reset = 3;
  metric.network_packets_dropped = 1;

  int iterations = argc > 2 ? iterations = atoi(argv[2]) : 1000000;

  // try running this binary through `perf stat` for both versions
  if (argc > 1 && argv[1] == std::string("dynamic")) {
    std::cout << "dynamic version, " << iterations << " iterations\n";
    while (iterations--) {
      export_metrics_dynamic(sink, metric);
    }
  } else {
    std::cout << "static version, " << iterations << " iterations\n";
    while (iterations--) {
      export_metrics_static(sink, metric);
    }
  }

  sink.report();

  return 0;
}
<commit_msg>fatal: fix minor build issue on gcc7<commit_after>/*
 * Copyright 2016-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/lib/cpp2/fatal/reflection.h>

#include <thrift/lib/cpp2/fatal/demo/gen-cpp2/metrics_fatal_types.h>

#include <folly/Conv.h>
#include <folly/init/Init.h>

#include <fatal/type/cat.h>

#include <iostream>

using namespace apache::thrift;
using namespace static_reflection::demo;

struct metrics_client {
  template <typename Metric, typename Value>
  void add(Metric const &name, Value const &value) {
    metrics_[name] += value;
  }

  void report() {
    for (auto const &i: metrics_) {
      std::cout << i.first << ": " << i.second << '\n';
    }
  }

private:
  std::unordered_map<std::string, std::intmax_t> metrics_;
};

// dynamic //

struct export_metric_dynamic {
  template <typename Member, std::size_t Index, typename T>
  void operator ()(
    fatal::indexed<Member, Index>,
    metrics_client &sink,
    T const &metrics,
    std::string const &prefix
  ) const {
    auto const key = prefix + fatal::z_data<typename Member::name>();
    auto const &value = Member::getter::ref(metrics);

    sink.add(key, value);
  }
};

std::string const kPrefix = "my_app.";

template <typename T>
void export_metrics_dynamic(metrics_client &sink, T const &metrics) {
  using info = reflect_struct<T>;

  fatal::foreach<typename info::members>(
    export_metric_dynamic(),
    sink,
    metrics,
    folly::to<std::string>(kPrefix, fatal::z_data<typename info::name>(), '.')
  );
}

// static //

struct export_metric_static {
  FATAL_S(prefix, "my_app");
  FATAL_S(dot, ".");

  template <typename Member, std::size_t Index, typename T>
  void operator ()(
    fatal::indexed<Member, Index>,
    metrics_client &sink,
    T const &metrics
  ) const {
    using info = reflect_struct<T>;
    using key = fatal::cat<
      prefix,
      dot,
      typename info::name,
      dot,
      typename Member::name
    >;

    auto const &value = Member::getter::ref(metrics);
    sink.add(fatal::z_data<key>(), value);
  }
};

template <typename T>
void export_metrics_static(metrics_client &sink, T const &metrics) {
  fatal::foreach<typename reflect_struct<T>::members>(
    export_metric_static(),
    sink,
    metrics
  );
}

// driver //

int main(int argc, char **argv) {
  folly::init(&argc, &argv);

  metrics_client sink;

  host_info metric;
  metric.cpu = 1;
  metric.memory = 12;
  metric.disk = 1234;
  metric.network_bytes_sent = 123;
  metric.network_bytes_received = 321;
  metric.network_retransmits = 2;
  metric.network_connection_reset = 3;
  metric.network_packets_dropped = 1;

  int iterations = argc > 2 ? atoi(argv[2]) : 1000000;

  // try running this binary through `perf stat` for both versions
  if (argc > 1 && argv[1] == std::string("dynamic")) {
    std::cout << "dynamic version, " << iterations << " iterations\n";
    while (iterations--) {
      export_metrics_dynamic(sink, metric);
    }
  } else {
    std::cout << "static version, " << iterations << " iterations\n";
    while (iterations--) {
      export_metrics_static(sink, metric);
    }
  }

  sink.report();

  return 0;
}
<|endoftext|>


<commit_before>//#include <vector>
//#include <map>
//#include <string>
#include <stdio.h>

#include "allocore/system/al_Printing.hpp"
#include "allocore/types/al_Array.hpp"
#include "allocore/graphics/al_Graphics.hpp"

namespace al{

Graphics::Graphics()
:	mRescaleNormal(0), mInImmediateMode(false)
{}

Graphics::~Graphics(){}

#define CS(t) case Graphics::t: return #t;
const char * toString(Graphics::DataType v){
	switch(v){
		CS(BYTE) CS(UBYTE) CS(SHORT) CS(USHORT) CS(INT) CS(UINT)
		CS(BYTES_2) CS(BYTES_3) CS(BYTES_4)
		CS(FLOAT) CS(DOUBLE)
		default: return "";
	}
}

const char * toString(Graphics::Format v){
	switch(v){
		CS(DEPTH_COMPONENT) CS(LUMINANCE) CS(LUMINANCE_ALPHA)
		CS(RED) CS(GREEN) CS(BLUE) CS(ALPHA)
		CS(RGB) CS(BGR) CS(RGBA) CS(BGRA)
		default: return "";
	}
}
#undef CS

int Graphics::numComponents(Format v){
	switch(v){
		case RGBA:
		case BGRA:				return 4;
		case RGB:
		case BGR:				return 3;
		case LUMINANCE_ALPHA:	return 2;
		case DEPTH_COMPONENT:
		case LUMINANCE:
		case RED:
		case GREEN:
		case BLUE:
		case ALPHA:				return 1;
		default:				return 0;
	};
}

int Graphics::numBytes(DataType v){
	#define CS(a,b) case a: return sizeof(b);
	switch(v){
		CS(BYTE, GLbyte)
		CS(UBYTE, GLubyte)
		CS(SHORT, GLshort)
		CS(USHORT, GLushort)
		CS(INT, GLint)
		CS(UINT, GLuint)
		CS(BYTES_2, char[2])
		CS(BYTES_3, char[3])
		CS(BYTES_4, char[4])
		CS(FLOAT, GLfloat)
		CS(DOUBLE, GLdouble)
		default: return 0;
	};
	#undef CS
}

template<> Graphics::DataType Graphics::toDataType<char>(){ return BYTE; }
template<> Graphics::DataType Graphics::toDataType<unsigned char>(){ return UBYTE; }
template<> Graphics::DataType Graphics::toDataType<short>(){ return SHORT; }
template<> Graphics::DataType Graphics::toDataType<unsigned short>(){ return USHORT; }
template<> Graphics::DataType Graphics::toDataType<int>(){ return INT; }
template<> Graphics::DataType Graphics::toDataType<unsigned int>(){ return UINT; }
template<> Graphics::DataType Graphics::toDataType<float>(){ return FLOAT; }
template<> Graphics::DataType Graphics::toDataType<double>(){ return DOUBLE; }

Graphics::DataType Graphics::toDataType(AlloTy v){
	switch(v){
		case AlloFloat32Ty: return FLOAT;
		case AlloFloat64Ty: return DOUBLE;
		case AlloSInt8Ty:	return BYTE;
		case AlloUInt8Ty:	return UBYTE;
		case AlloSInt16Ty:	return SHORT;
		case AlloUInt16Ty:	return USHORT;
		case AlloSInt32Ty:	return INT;
		case AlloUInt32Ty:	return UINT;
		default:			return BYTE;
	}
}

AlloTy Graphics :: toAlloTy(Graphics::DataType v) {
	switch (v) {
		case BYTE:		return AlloSInt8Ty;
		case UBYTE:		return AlloUInt8Ty;
		case SHORT:		return AlloSInt16Ty;
		case USHORT:	return AlloUInt16Ty;
		case INT:		return AlloSInt32Ty;
		case UINT:		return AlloUInt32Ty;
		case FLOAT:		return AlloFloat32Ty;
		case DOUBLE:	return AlloFloat64Ty;
		default:		return AlloVoidTy;
	}
}

const char * Graphics::errorString(bool verbose){
	GLenum err = glGetError();
	#define CS(GL_ERR, desc) case GL_ERR: return verbose ? #GL_ERR ", " desc : #GL_ERR;
	switch(err){
		case GL_NO_ERROR: return "";
		CS(GL_INVALID_ENUM, "An unacceptable value is specified for an enumerated argument.")
		CS(GL_INVALID_VALUE, "A numeric argument is out of range.")
		CS(GL_INVALID_OPERATION, "The specified operation is not allowed in the current state.")
	#ifdef GL_INVALID_FRAMEBUFFER_OPERATION
		CS(GL_INVALID_FRAMEBUFFER_OPERATION, "The framebuffer object is not complete.")
	#endif
		CS(GL_OUT_OF_MEMORY, "There is not enough memory left to execute the command.")
		CS(GL_STACK_OVERFLOW, "This command would cause a stack overflow.")
		CS(GL_STACK_UNDERFLOW, "This command would cause a stack underflow.")
	#ifdef GL_TABLE_TOO_LARGE
		CS(GL_TABLE_TOO_LARGE, "The specified table exceeds the implementation's maximum supported table size.")
	#endif
		default: return "Unknown error code.";
	}
	#undef CS
}

bool Graphics::error(const char * msg, int ID){
	const char * errStr = errorString();
	if(errStr[0]){
		if(ID>=0)	AL_WARN_ONCE("Error %s (id=%d): %s", msg, ID, errStr);
		else		AL_WARN_ONCE("Error %s: %s", msg, errStr);
		return true;
	}
	return false;
}

void Graphics::antialiasing(AntiAliasMode v){
	glHint(GL_POINT_SMOOTH_HINT, v);
	glHint(GL_LINE_SMOOTH_HINT, v);
	glHint(GL_POLYGON_SMOOTH_HINT, v);

	if (FASTEST != v) {
		glEnable(GL_POLYGON_SMOOTH);
		glEnable(GL_LINE_SMOOTH);
		glEnable(GL_POINT_SMOOTH);
	} else {
		glDisable(GL_POLYGON_SMOOTH);
		glDisable(GL_LINE_SMOOTH);
		glDisable(GL_POINT_SMOOTH);
	}
}

void Graphics::fog(float end, float start, const Color& c){
	glEnable(GL_FOG);
	glFogi(GL_FOG_MODE, GL_LINEAR);
	glFogf(GL_FOG_START, start); glFogf(GL_FOG_END, end);
	float fogColor[4] = {c.r, c.g, c.b, c.a};
	glFogfv(GL_FOG_COLOR, fogColor);
}

void Graphics::viewport(int x, int y, int width, int height) {
	glViewport(x, y, width, height);
	enable(SCISSOR_TEST);
	glScissor(x, y, width, height);
}

Viewport Graphics::viewport() const {
	GLint vp[4];
	glGetIntegerv(GL_VIEWPORT, vp);
	return Viewport(vp[0], vp[1], vp[2], vp[3]);
}

// Immediate Mode
void Graphics::begin(Primitive v) {
	// clear buffers
	mMesh.reset();

	// start primitive drawing
	mMesh.primitive(v);
	mInImmediateMode = true;
}

void Graphics::end() {
	draw(mMesh);
	mInImmediateMode = false;
}

void Graphics::vertex(double x, double y, double z) {
	if(mInImmediateMode) {
		// make sure all buffers are the same size if > 0
		mMesh.vertex(x, y, z);
		mMesh.equalizeBuffers();
	}
}

void Graphics::texCoord(double u, double v) {
	if(mInImmediateMode) {
		mMesh.texCoord(u, v);
	}
}

void Graphics::texCoord(double s, double t, double r) {
	if(mInImmediateMode) {
		mMesh.texCoord(s, t, r);
	}
}

void Graphics::normal(double x, double y, double z) {
	if(mInImmediateMode) {
		mMesh.normal(x, y, z);
	}
}

void Graphics::color(double r, double g, double b, double a) {
	if(mInImmediateMode) {
		mMesh.color(r, g, b, a);
	} else {
		currentColor(r, g, b, a);
	}
}

// Buffer drawing
void Graphics::draw(int num_vertices, const Mesh& m){
	draw(m, num_vertices);
}

void Graphics::draw(const Mesh& v, int count, int begin){

	const int Nv = v.vertices().size();
	if(0 == Nv) return; // nothing to draw, so just return...

	const int Ni = v.indices().size();

	const int Nmax = Ni ? Ni : Nv;

	// Adjust negative amounts
	if(count < 0) count += Nmax+1;
	if(begin < 0) begin += Nmax+1;

	// Safety checks...
	//if(count > Nmax) count = Nmax;
	//if(begin+count >= iend) return;

	if(begin >= Nmax) return;	// Begin index past end?
	if(begin + count > Nmax){	// If end index past end, then truncate it
		count = Nmax - begin;
	}

	const int Nc = v.colors().size();
	const int Nci= v.coloris().size();
	const int Nn = v.normals().size();
	const int Nt1= v.texCoord1s().size();
	const int Nt2= v.texCoord2s().size();
	const int Nt3= v.texCoord3s().size();

	//printf("client %d, GPU %d\n", clientSide, gpuSide);
	//printf("Nv %i Nc %i Nn %i Nt2 %i Nt3 %i Ni %i\n", Nv, Nc, Nn, Nt2, Nt3, Ni);

	// Enable arrays and set pointers...
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, &v.vertices()[0]);

	if(Nn >= Nv){
		glEnableClientState(GL_NORMAL_ARRAY);
		glNormalPointer(GL_FLOAT, 0, &v.normals()[0]);
	}

	if(Nc >= Nv){
		glEnableClientState(GL_COLOR_ARRAY);
		glColorPointer(4, GL_FLOAT, 0, &v.colors()[0]);
	}
	else if(Nci >= Nv){
		glEnableClientState(GL_COLOR_ARRAY);
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, &v.coloris()[0]);
		//printf("using integer colors\n");
	}
	else if(0 == Nc && 0 == Nci){
		// just use whatever the last glColor() call used!
	}
	else{
		if(Nc)
			//glColor4f(v.colors()[0][0], v.colors()[0][1], v.colors()[0][2], v.colors()[0][3]);
			glColor4fv(v.colors()[0].components);
		else
			glColor3ubv(v.coloris()[0].components);
	}

	if(Nt1 >= Nv){
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(1, GL_FLOAT, 0, &v.texCoord1s()[0]);
	}
	else if(Nt2 >= Nv){
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(2, GL_FLOAT, 0, &v.texCoord2s()[0]);
	}
	else if(Nt3 >= Nv){
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(3, GL_FLOAT, 0, &v.texCoord3s()[0]);
	}

	// Draw
	if(Ni){
		glDrawElements(
			((Graphics::Primitive)v.primitive()),
			count, // number of indexed elements to render
			GL_UNSIGNED_INT,
			&v.indices()[begin]
		);
	}
	else{
		glDrawArrays(
			((Graphics::Primitive)v.primitive()),
			begin,
			count
		);
	}

	// Disable arrays
	glDisableClientState(GL_VERTEX_ARRAY);
	if(Nn)					glDisableClientState(GL_NORMAL_ARRAY);
	if(Nc || Nci)			glDisableClientState(GL_COLOR_ARRAY);
	if(Nt1 || Nt2 || Nt3)	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

// draw a MeshVBO
void Graphics::draw(MeshVBO& meshVBO) {
	if (!meshVBO.isBound()) meshVBO.bind();

	if (meshVBO.hasIndices()) glDrawElements(meshVBO.primitive(), meshVBO.getNumIndices(), GL_UNSIGNED_INT, NULL);
	else glDrawArrays(meshVBO.primitive(), 0, meshVBO.getNumVertices());

	meshVBO.unbind();
}

void Graphics::onCreate(){
	GPUObject::mID = 1; // must be non-zero to flag creation
	mRescaleNormal = 0;
}

void Graphics::onDestroy(){
}

} // al::
<commit_msg>Graphics: add support for Mesh stroke<commit_after>//#include <vector>
//#include <map>
//#include <string>
#include <stdio.h>

#include "allocore/system/al_Printing.hpp"
#include "allocore/types/al_Array.hpp"
#include "allocore/graphics/al_Graphics.hpp"

namespace al{

Graphics::Graphics()
:	mRescaleNormal(0), mInImmediateMode(false)
{}

Graphics::~Graphics(){}

#define CS(t) case Graphics::t: return #t;
const char * toString(Graphics::DataType v){
	switch(v){
		CS(BYTE) CS(UBYTE) CS(SHORT) CS(USHORT) CS(INT) CS(UINT)
		CS(BYTES_2) CS(BYTES_3) CS(BYTES_4)
		CS(FLOAT) CS(DOUBLE)
		default: return "";
	}
}

const char * toString(Graphics::Format v){
	switch(v){
		CS(DEPTH_COMPONENT) CS(LUMINANCE) CS(LUMINANCE_ALPHA)
		CS(RED) CS(GREEN) CS(BLUE) CS(ALPHA)
		CS(RGB) CS(BGR) CS(RGBA) CS(BGRA)
		default: return "";
	}
}
#undef CS

int Graphics::numComponents(Format v){
	switch(v){
		case RGBA:
		case BGRA:				return 4;
		case RGB:
		case BGR:				return 3;
		case LUMINANCE_ALPHA:	return 2;
		case DEPTH_COMPONENT:
		case LUMINANCE:
		case RED:
		case GREEN:
		case BLUE:
		case ALPHA:				return 1;
		default:				return 0;
	};
}

int Graphics::numBytes(DataType v){
	#define CS(a,b) case a: return sizeof(b);
	switch(v){
		CS(BYTE, GLbyte)
		CS(UBYTE, GLubyte)
		CS(SHORT, GLshort)
		CS(USHORT, GLushort)
		CS(INT, GLint)
		CS(UINT, GLuint)
		CS(BYTES_2, char[2])
		CS(BYTES_3, char[3])
		CS(BYTES_4, char[4])
		CS(FLOAT, GLfloat)
		CS(DOUBLE, GLdouble)
		default: return 0;
	};
	#undef CS
}

template<> Graphics::DataType Graphics::toDataType<char>(){ return BYTE; }
template<> Graphics::DataType Graphics::toDataType<unsigned char>(){ return UBYTE; }
template<> Graphics::DataType Graphics::toDataType<short>(){ return SHORT; }
template<> Graphics::DataType Graphics::toDataType<unsigned short>(){ return USHORT; }
template<> Graphics::DataType Graphics::toDataType<int>(){ return INT; }
template<> Graphics::DataType Graphics::toDataType<unsigned int>(){ return UINT; }
template<> Graphics::DataType Graphics::toDataType<float>(){ return FLOAT; }
template<> Graphics::DataType Graphics::toDataType<double>(){ return DOUBLE; }

Graphics::DataType Graphics::toDataType(AlloTy v){
	switch(v){
		case AlloFloat32Ty: return FLOAT;
		case AlloFloat64Ty: return DOUBLE;
		case AlloSInt8Ty:	return BYTE;
		case AlloUInt8Ty:	return UBYTE;
		case AlloSInt16Ty:	return SHORT;
		case AlloUInt16Ty:	return USHORT;
		case AlloSInt32Ty:	return INT;
		case AlloUInt32Ty:	return UINT;
		default:			return BYTE;
	}
}

AlloTy Graphics :: toAlloTy(Graphics::DataType v) {
	switch (v) {
		case BYTE:		return AlloSInt8Ty;
		case UBYTE:		return AlloUInt8Ty;
		case SHORT:		return AlloSInt16Ty;
		case USHORT:	return AlloUInt16Ty;
		case INT:		return AlloSInt32Ty;
		case UINT:		return AlloUInt32Ty;
		case FLOAT:		return AlloFloat32Ty;
		case DOUBLE:	return AlloFloat64Ty;
		default:		return AlloVoidTy;
	}
}

const char * Graphics::errorString(bool verbose){
	GLenum err = glGetError();
	#define CS(GL_ERR, desc) case GL_ERR: return verbose ? #GL_ERR ", " desc : #GL_ERR;
	switch(err){
		case GL_NO_ERROR: return "";
		CS(GL_INVALID_ENUM, "An unacceptable value is specified for an enumerated argument.")
		CS(GL_INVALID_VALUE, "A numeric argument is out of range.")
		CS(GL_INVALID_OPERATION, "The specified operation is not allowed in the current state.")
	#ifdef GL_INVALID_FRAMEBUFFER_OPERATION
		CS(GL_INVALID_FRAMEBUFFER_OPERATION, "The framebuffer object is not complete.")
	#endif
		CS(GL_OUT_OF_MEMORY, "There is not enough memory left to execute the command.")
		CS(GL_STACK_OVERFLOW, "This command would cause a stack overflow.")
		CS(GL_STACK_UNDERFLOW, "This command would cause a stack underflow.")
	#ifdef GL_TABLE_TOO_LARGE
		CS(GL_TABLE_TOO_LARGE, "The specified table exceeds the implementation's maximum supported table size.")
	#endif
		default: return "Unknown error code.";
	}
	#undef CS
}

bool Graphics::error(const char * msg, int ID){
	const char * errStr = errorString();
	if(errStr[0]){
		if(ID>=0)	AL_WARN_ONCE("Error %s (id=%d): %s", msg, ID, errStr);
		else		AL_WARN_ONCE("Error %s: %s", msg, errStr);
		return true;
	}
	return false;
}

void Graphics::antialiasing(AntiAliasMode v){
	glHint(GL_POINT_SMOOTH_HINT, v);
	glHint(GL_LINE_SMOOTH_HINT, v);
	glHint(GL_POLYGON_SMOOTH_HINT, v);

	if (FASTEST != v) {
		glEnable(GL_POLYGON_SMOOTH);
		glEnable(GL_LINE_SMOOTH);
		glEnable(GL_POINT_SMOOTH);
	} else {
		glDisable(GL_POLYGON_SMOOTH);
		glDisable(GL_LINE_SMOOTH);
		glDisable(GL_POINT_SMOOTH);
	}
}

void Graphics::fog(float end, float start, const Color& c){
	glEnable(GL_FOG);
	glFogi(GL_FOG_MODE, GL_LINEAR);
	glFogf(GL_FOG_START, start); glFogf(GL_FOG_END, end);
	float fogColor[4] = {c.r, c.g, c.b, c.a};
	glFogfv(GL_FOG_COLOR, fogColor);
}

void Graphics::viewport(int x, int y, int width, int height) {
	glViewport(x, y, width, height);
	enable(SCISSOR_TEST);
	glScissor(x, y, width, height);
}

Viewport Graphics::viewport() const {
	GLint vp[4];
	glGetIntegerv(GL_VIEWPORT, vp);
	return Viewport(vp[0], vp[1], vp[2], vp[3]);
}

// Immediate Mode
void Graphics::begin(Primitive v) {
	// clear buffers
	mMesh.reset();

	// start primitive drawing
	mMesh.primitive(v);
	mInImmediateMode = true;
}

void Graphics::end() {
	draw(mMesh);
	mInImmediateMode = false;
}

void Graphics::vertex(double x, double y, double z) {
	if(mInImmediateMode) {
		// make sure all buffers are the same size if > 0
		mMesh.vertex(x, y, z);
		mMesh.equalizeBuffers();
	}
}

void Graphics::texCoord(double u, double v) {
	if(mInImmediateMode) {
		mMesh.texCoord(u, v);
	}
}

void Graphics::texCoord(double s, double t, double r) {
	if(mInImmediateMode) {
		mMesh.texCoord(s, t, r);
	}
}

void Graphics::normal(double x, double y, double z) {
	if(mInImmediateMode) {
		mMesh.normal(x, y, z);
	}
}

void Graphics::color(double r, double g, double b, double a) {
	if(mInImmediateMode) {
		mMesh.color(r, g, b, a);
	} else {
		currentColor(r, g, b, a);
	}
}

// Buffer drawing
void Graphics::draw(int num_vertices, const Mesh& m){
	draw(m, num_vertices);
}

void Graphics::draw(const Mesh& m, int count, int begin){

	const int Nv = m.vertices().size();
	if(0 == Nv) return; // nothing to draw, so just return...

	const int Ni = m.indices().size();

	const int Nmax = Ni ? Ni : Nv;

	// Adjust negative amounts
	if(count < 0) count += Nmax+1;
	if(begin < 0) begin += Nmax+1;

	// Safety checks...
	//if(count > Nmax) count = Nmax;
	//if(begin+count >= iend) return;

	if(begin >= Nmax) return;	// Begin index past end?
	if(begin + count > Nmax){	// If end index past end, then truncate it
		count = Nmax - begin;
	}

	const int Nc = m.colors().size();
	const int Nci= m.coloris().size();
	const int Nn = m.normals().size();
	const int Nt1= m.texCoord1s().size();
	const int Nt2= m.texCoord2s().size();
	const int Nt3= m.texCoord3s().size();

	//printf("client %d, GPU %d\n", clientSide, gpuSide);
	//printf("Nv %i Nc %i Nn %i Nt2 %i Nt3 %i Ni %i\n", Nv, Nc, Nn, Nt2, Nt3, Ni);

	// Enable arrays and set pointers...
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, &m.vertices()[0]);

	if(Nn >= Nv){
		glEnableClientState(GL_NORMAL_ARRAY);
		glNormalPointer(GL_FLOAT, 0, &m.normals()[0]);
	}

	if(Nc >= Nv){
		glEnableClientState(GL_COLOR_ARRAY);
		glColorPointer(4, GL_FLOAT, 0, &m.colors()[0]);
	}
	else if(Nci >= Nv){
		glEnableClientState(GL_COLOR_ARRAY);
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, &m.coloris()[0]);
		//printf("using integer colors\n");
	}
	else if(0 == Nc && 0 == Nci){
		// just use whatever the last glColor() call used!
	}
	else{
		if(Nc)
			//glColor4f(m.colors()[0][0], m.colors()[0][1], m.colors()[0][2], m.colors()[0][3]);
			glColor4fv(m.colors()[0].components);
		else
			glColor3ubv(m.coloris()[0].components);
	}

	if(Nt1 >= Nv){
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(1, GL_FLOAT, 0, &m.texCoord1s()[0]);
	}
	else if(Nt2 >= Nv){
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(2, GL_FLOAT, 0, &m.texCoord2s()[0]);
	}
	else if(Nt3 >= Nv){
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(3, GL_FLOAT, 0, &m.texCoord3s()[0]);
	}

	auto prim = (Graphics::Primitive)m.primitive();

	if(m.stroke() > 0.f){
		switch(prim){
		case LINES: case LINE_STRIP: case LINE_LOOP:
			glLineWidth(m.stroke());
			break;
		case POINTS:
			glPointSize(m.stroke());
			break;
		default:;
		}
	}

	// Draw
	if(Ni){
		// Here, 'count' is the number of indexed elements to render
		glDrawElements(prim, count, GL_UNSIGNED_INT, &m.indices()[begin]);
	}
	else{
		glDrawArrays(prim, begin, count);
	}

	// Disable arrays
	glDisableClientState(GL_VERTEX_ARRAY);
	if(Nn)					glDisableClientState(GL_NORMAL_ARRAY);
	if(Nc || Nci)			glDisableClientState(GL_COLOR_ARRAY);
	if(Nt1 || Nt2 || Nt3)	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

// draw a MeshVBO
void Graphics::draw(MeshVBO& meshVBO) {
	if (!meshVBO.isBound()) meshVBO.bind();

	if (meshVBO.hasIndices()) glDrawElements(meshVBO.primitive(), meshVBO.getNumIndices(), GL_UNSIGNED_INT, NULL);
	else glDrawArrays(meshVBO.primitive(), 0, meshVBO.getNumVertices());

	meshVBO.unbind();
}

void Graphics::onCreate(){
	GPUObject::mID = 1; // must be non-zero to flag creation
	mRescaleNormal = 0;
}

void Graphics::onDestroy(){
}

} // al::
<|endoftext|>


<commit_before>//
// file : mesh.hpp
// in : file:///home/tim/projects/hydra/hydra/geometry/mesh.hpp
//
// created by : Timothée Feuillet
// date: Sat Aug 27 2016 15:44:40 GMT+0200 (CEST)
//
//
// Copyright (c) 2016 Timothée Feuillet
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#ifndef __N_30181263603267010772_2083712051_MESH_HPP__
#define __N_30181263603267010772_2083712051_MESH_HPP__

#include <deque>

#include "../vulkan/vulkan.hpp"
#include "../utilities/transfer.hpp"
#include "../utilities/memory_allocation.hpp"

namespace neam
{
  namespace hydra
  {
    /// \brief Hold informations about geometry (buffers, vertex type/description)
    ///
    /// A valid usage of this class is
    ///  - step 1: tell him what kind of buffer you want, with what size (add_buffer())
    ///  - step 2: setup vertex binding and geometry type
    ///            (set_topology(), has_primitive_restart(),
    ///            get_vertex_input_state())
    ///  - step 3: allocate the memory on the device with the provided requirements
    ///            and bind the memory to that mesh
    ///            (get_memory_requirements(), bind_memory_area())
    ///  - step 4: upload data to the different buffers of the mesh (preferably
    ///            with a batch_transfers object) (transfer_data())
    class mesh
    {
      public:
        /// \brief Create a mesh without anything
        mesh(vk::device &_dev) : dev(_dev) {}

        mesh(mesh &&o)
          : dev(o.dev), topology(o.topology), primitive_restart(o.primitive_restart),
            buffers(std::move(o.buffers)), first_binding(o.first_binding), index_type(o.index_type),
            buffers_offsets(std::move(o.buffers_offsets)), dev_mem(o.dev_mem), index_buffer_present(o.index_buffer_present),
            pvis(std::move(o.pvis))
        {
        }

        mesh &operator = (mesh &&o)
        {
          if (&o == this)
            return *this;
          check::on_vulkan_error::n_assert(&dev == &o.dev, "can't assign two meshes with different vulkan devices");
          topology = o.topology;
          primitive_restart = o.primitive_restart;

          buffers = std::move(o.buffers);
          first_binding = o.first_binding;
          index_type = o.index_type;

          buffers_offsets = std::move(o.buffers_offsets);
          dev_mem = o.dev_mem;
          index_buffer_present = o.index_buffer_present;

          pvis = std::move(o.pvis);
          return *this;
        }

        ~mesh() { allocation.free(); }

        /// \brief Add a buffer
        void add_buffer(size_t size, VkBufferUsageFlags usage, VkBufferCreateFlags flags = 0)
        {
          if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) // TODO: test if the vertex buffer usage flag is also set
          {
            check::on_vulkan_error::n_assert(index_buffer_present == false, "meshes can't have more than one index buffer");

            index_buffer_present = true;
            buffers.emplace_front(dev, size, usage, flags);
          }
          else
          {
// #ifndef HYDRA_NO_MESSAGES
//             if ((usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT))
//               neam::cr::out.info() << LOGGER_INFO << "adding a buffer with VK_BUFFER_USAGE_INDEX_BUFFER_BIT as a vertex buffer" << neam::cr::newline
//                                    << "'cause an index buffer is already present and this buffer has another usage bit enabled";
// #endif
            buffers.emplace_back(dev, size, usage, flags);
          }
        }

        /// \brief Set the binding of the first vertex buffer of the mesh.
        /// The second buffer will have a binding point of fb + 1, and so on.
        void set_first_binding(size_t fb)
        {
          first_binding = fb;
        }

        /// \brief Return true if the mesh has an index buffer
        bool has_index_buffer() const { return index_buffer_present; }

        /// \brief Return the topology of the mesh
        VkPrimitiveTopology get_topology() const { return topology; }

        /// \brief Set the topology of the mesh
        void set_topology(VkPrimitiveTopology _topology) { topology = _topology; }

        /// \brief Return if the mesh uses primitive restart
        bool has_primitive_restart() const { return primitive_restart; }

        /// \brief Set if the mesh uses primitive restart
        void has_primitive_restart(bool restart) { primitive_restart = restart; }

        /// \brief A nice way to describe binding & attributes of the mesh
        vk::pipeline_vertex_input_state &get_vertex_input_state() { return pvis; }

        /// \brief Clear the buffers (destroy them, but keep the same state)
        void clear_buffer() { buffers.clear(); index_buffer_present = false; }

        /// \brief Return the memory needed for all the buffers of the mesh
        /// \note If you want a number to allocate memory, use get_memory_requirements()
        /// \see get_memory_requirements()
        size_t get_mesh_memory_consumption() const
        {
          size_t ret = 0;
          for (const vk::buffer &it : buffers)
            ret += it.size();
          return ret;
        }

        /// \brief Return the qty of memory needed to have a contiguous chunk of memory holding
        /// All the buffers
        /// \note Size may vary depending on the offset the said memory
        size_t get_mesh_aligned_memory_consumption() const
        {
          size_t ret = 0;
          for (const vk::buffer &it : buffers)
          {
            auto reqs = it.get_memory_requirements();
            if ((ret % reqs.alignment) != 0)
              ret += (reqs.alignment - (ret % reqs.alignment));
            ret += reqs.size;
          }
          return ret;
        }

        /// \brief Return the memory requirements of the mesh
        VkMemoryRequirements get_memory_requirements() const
        {
          VkMemoryRequirements ret;
          ret.size = 0;
          ret.memoryTypeBits = 0;
          if (buffers.size())
            ret.alignment = buffers[0].get_memory_requirements().alignment;
          else
            ret.alignment = 0;
          for (const vk::buffer &it : buffers)
          {
            auto reqs = it.get_memory_requirements();
            if ((ret.size % reqs.alignment) != 0)
              ret.size += (reqs.alignment - (ret.size % reqs.alignment));
            ret.size += reqs.size;
            ret.memoryTypeBits |= reqs.memoryTypeBits;
          }
          return ret;
        }

        /// \brief Allocate and bind some memory for the batch transfer
        /// The memory is then freed when the transfer object is destructed
        void allocate_memory(memory_allocator &mem_alloc, VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        {
          _bind_memory_area(mem_alloc.allocate_memory(get_memory_requirements(), flags));
        }

        /// \brief Bind a memory area to every single buffers
        /// (it does alignement & everything else).
        /// \see get_memory_requirements()
        /// \note The memory is freed after the end of the mesh's life
        void _bind_memory_area(const memory_allocation &ma)
        {
          _bind_memory_area(*ma.mem(), ma.offset());
          allocation.free();
          allocation = ma;
        }

        /// \brief Bind a memory area to every single buffers
        /// (it does alignement & everything else).
        /// \see get_memory_requirements()
        void _bind_memory_area(const vk::device_memory &dm, size_t offset)
        {
          buffers_offsets.clear();
          for (vk::buffer &it : buffers)
          {
            auto reqs = it.get_memory_requirements();
            if ((offset % reqs.alignment) != 0)
              offset += (reqs.alignment - (offset % reqs.alignment));

            buffers_offsets.push_back(offset);
            it.bind_memory(dm, offset);

            offset += reqs.size;
          }
          dev_mem = &dm;
        }

        /// \brief Return the associated device memory (if any)
        const vk::device_memory *_get_device_memory() { return dev_mem; }

        /// \brief Return the offset of a buffer (may throw if no memory)
        size_t _get_buffer_offset(size_t buffer_index) const { return buffers_offsets.at(buffer_index); }

        /// \brief Map the buffer to host memory
        /// \note The bound memory MUST be host visible
        void *_map_buffer(size_t buffer_index) const { return dev_mem->map_memory(buffers_offsets.at(buffer_index), buffers[buffer_index].size()); }

        /// \brief Transfer some data to a buffer (using a batch transfer utility)
        /// \param signal_semaphore If specified, a semaphore that will become signaled when the transfer as been completed
        void transfer_data(batch_transfers &bt, size_t buffer_index, size_t data_size, const void *_data, vk::semaphore *signal_semaphore = nullptr, vk::fence *signal_fence = nullptr)
        {
          transfer_data(bt, buffer_index, 0, data_size, _data, signal_semaphore, signal_fence);
        }

        /// \brief Transfer some data to a buffer (using a batch transfer utility)
        /// \param signal_semaphore If specified, a semaphore that will become signaled when the transfer as been completed
        void transfer_data(batch_transfers &bt, size_t buffer_index, size_t offset, size_t data_size, const void *_data, vk::semaphore *signal_semaphore = nullptr, vk::fence *signal_fence = nullptr)
        {
          bt.add_transfer(buffers.at(buffer_index), offset, data_size, _data, signal_semaphore, signal_fence);
        }

        /// \brief Call this to setup the vertex description
        /// \see get_vertex_input_state()
        void setup_vertex_description(vk::pipeline_creator &pc)
        {
          pc.get_vertex_input_state() = pvis;
          pc.get_input_assembly_state().set_topology(topology).enable_primitive_restart(primitive_restart);
        }

        /// \brief Bind the buffers to a command buffer
        void bind(vk::command_buffer_recorder &cbr) const
        {
          std::vector<const vk::buffer *> vct_buf;
          vct_buf.reserve(buffers.size());
          if (index_buffer_present)
            cbr.bind_index_buffer(buffers[0], index_type);
          for (size_t i = (index_buffer_present ? 1 : 0); i < buffers.size(); ++i)
            vct_buf.push_back(&buffers[i]);
          cbr.bind_vertex_buffers(first_binding, vct_buf);
        }

      public:
        /// \brief Return the buffers. If there's an index buffer, it has index 0
        /// \note marked as advanced
        std::deque<vk::buffer> &_get_buffers() { return buffers; }

      protected:
        vk::device &dev;

        VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
        bool primitive_restart = false;

        std::deque<vk::buffer> buffers; // If there's an index buffer, it's the first one

        size_t first_binding = 0;
        VkIndexType index_type = VK_INDEX_TYPE_UINT16;

        std::deque<size_t> buffers_offsets;
        memory_allocation allocation;
        const vk::device_memory *dev_mem = nullptr;

        bool index_buffer_present = false;

        vk::pipeline_vertex_input_state pvis;
    };
  } // namespace hydra
} // namespace neam

#endif // __N_30181263603267010772_2083712051_MESH_HPP__

<commit_msg>[GEOM/MESH]: Fix some issues with memory requirements<commit_after>//
// file : mesh.hpp
// in : file:///home/tim/projects/hydra/hydra/geometry/mesh.hpp
//
// created by : Timothée Feuillet
// date: Sat Aug 27 2016 15:44:40 GMT+0200 (CEST)
//
//
// Copyright (c) 2016 Timothée Feuillet
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#ifndef __N_30181263603267010772_2083712051_MESH_HPP__
#define __N_30181263603267010772_2083712051_MESH_HPP__

#include <deque>

#include "../vulkan/vulkan.hpp"
#include "../utilities/transfer.hpp"
#include "../utilities/memory_allocation.hpp"

namespace neam
{
  namespace hydra
  {
    /// \brief Hold informations about geometry (buffers, vertex type/description)
    ///
    /// A valid usage of this class is
    ///  - step 1: tell him what kind of buffer you want, with what size (add_buffer())
    ///  - step 2: setup vertex binding and geometry type
    ///            (set_topology(), has_primitive_restart(),
    ///            get_vertex_input_state())
    ///  - step 3: allocate the memory on the device with the provided requirements
    ///            and bind the memory to that mesh
    ///            (get_memory_requirements(), bind_memory_area())
    ///  - step 4: upload data to the different buffers of the mesh (preferably
    ///            with a batch_transfers object) (transfer_data())
    class mesh
    {
      public:
        /// \brief Create a mesh without anything
        mesh(vk::device &_dev) : dev(_dev) {}

        mesh(mesh &&o)
          : dev(o.dev), topology(o.topology), primitive_restart(o.primitive_restart),
            buffers(std::move(o.buffers)), first_binding(o.first_binding), index_type(o.index_type),
            buffers_offsets(std::move(o.buffers_offsets)), dev_mem(o.dev_mem), index_buffer_present(o.index_buffer_present),
            pvis(std::move(o.pvis))
        {
        }

        mesh &operator = (mesh &&o)
        {
          if (&o == this)
            return *this;
          check::on_vulkan_error::n_assert(&dev == &o.dev, "can't assign two meshes with different vulkan devices");
          topology = o.topology;
          primitive_restart = o.primitive_restart;

          buffers = std::move(o.buffers);
          first_binding = o.first_binding;
          index_type = o.index_type;

          buffers_offsets = std::move(o.buffers_offsets);
          dev_mem = o.dev_mem;
          index_buffer_present = o.index_buffer_present;

          pvis = std::move(o.pvis);
          return *this;
        }

        ~mesh() { allocation.free(); }

        /// \brief Add a buffer
        void add_buffer(size_t size, VkBufferUsageFlags usage, VkBufferCreateFlags flags = 0)
        {
          if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) // TODO: test if the vertex buffer usage flag is also set
          {
            check::on_vulkan_error::n_assert(index_buffer_present == false, "meshes can't have more than one index buffer");

            index_buffer_present = true;
            buffers.emplace_front(dev, size, usage, flags);
          }
          else
          {
// #ifndef HYDRA_NO_MESSAGES
//             if ((usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT))
//               neam::cr::out.info() << LOGGER_INFO << "adding a buffer with VK_BUFFER_USAGE_INDEX_BUFFER_BIT as a vertex buffer" << neam::cr::newline
//                                    << "'cause an index buffer is already present and this buffer has another usage bit enabled";
// #endif
            buffers.emplace_back(dev, size, usage, flags);
          }
        }

        /// \brief Set the binding of the first vertex buffer of the mesh.
        /// The second buffer will have a binding point of fb + 1, and so on.
        void set_first_binding(size_t fb)
        {
          first_binding = fb;
        }

        /// \brief Return true if the mesh has an index buffer
        bool has_index_buffer() const { return index_buffer_present; }

        /// \brief Return the topology of the mesh
        VkPrimitiveTopology get_topology() const { return topology; }

        /// \brief Set the topology of the mesh
        void set_topology(VkPrimitiveTopology _topology) { topology = _topology; }

        /// \brief Return if the mesh uses primitive restart
        bool has_primitive_restart() const { return primitive_restart; }

        /// \brief Set if the mesh uses primitive restart
        void has_primitive_restart(bool restart) { primitive_restart = restart; }

        /// \brief A nice way to describe binding & attributes of the mesh
        vk::pipeline_vertex_input_state &get_vertex_input_state() { return pvis; }

        /// \brief Clear the buffers (destroy them, but keep the same state)
        void clear_buffer() { buffers.clear(); index_buffer_present = false; }

        /// \brief Return the memory needed for all the buffers of the mesh
        /// \note If you want a number to allocate memory, use get_memory_requirements()
        /// \see get_memory_requirements()
        size_t get_mesh_memory_consumption() const
        {
          size_t ret = 0;
          for (const vk::buffer &it : buffers)
            ret += it.size();
          return ret;
        }

        /// \brief Return the qty of memory needed to have a contiguous chunk of memory holding
        /// All the buffers
        /// \note Size may vary depending on the offset the said memory
        size_t get_mesh_aligned_memory_consumption() const
        {
          size_t ret = 0;
          for (const vk::buffer &it : buffers)
          {
            VkMemoryRequirements reqs = it.get_memory_requirements();
            if ((ret % reqs.alignment) != 0)
              ret += (reqs.alignment - (ret % reqs.alignment));
            ret += reqs.size;
          }
          return ret;
        }

        /// \brief Return the memory requirements of the mesh
        VkMemoryRequirements get_memory_requirements() const
        {
          VkMemoryRequirements ret;
          ret.size = 0;
          ret.memoryTypeBits = ~0;
          if (buffers.size())
            ret.alignment = buffers[0].get_memory_requirements().alignment;
          else
            ret.alignment = 1;
          for (const vk::buffer &it : buffers)
          {
            VkMemoryRequirements reqs = it.get_memory_requirements();
            if ((ret.size % reqs.alignment) != 0)
              ret.size += (reqs.alignment - (ret.size % reqs.alignment));
            ret.size += reqs.size;
            ret.memoryTypeBits &= reqs.memoryTypeBits;
          }
          return ret;
        }

        /// \brief Allocate and bind some memory for the batch transfer
        /// The memory is then freed when the transfer object is destructed
        void allocate_memory(memory_allocator &mem_alloc, VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        {
          _bind_memory_area(mem_alloc.allocate_memory(get_memory_requirements(), flags));
        }

        /// \brief Bind a memory area to every single buffers
        /// (it does alignement & everything else).
        /// \see get_memory_requirements()
        /// \note The memory is freed after the end of the mesh's life
        void _bind_memory_area(const memory_allocation &ma)
        {
          _bind_memory_area(*ma.mem(), ma.offset());
          allocation.free();
          allocation = ma;
        }

        /// \brief Bind a memory area to every single buffers
        /// (it does alignement & everything else).
        /// \see get_memory_requirements()
        void _bind_memory_area(const vk::device_memory &dm, size_t offset)
        {
          buffers_offsets.clear();
          for (vk::buffer &it : buffers)
          {
            auto reqs = it.get_memory_requirements();
            if ((offset % reqs.alignment) != 0)
              offset += (reqs.alignment - (offset % reqs.alignment));

            buffers_offsets.push_back(offset);
            it.bind_memory(dm, offset);

            offset += reqs.size;
          }
          dev_mem = &dm;
        }

        /// \brief Return the associated device memory (if any)
        const vk::device_memory *_get_device_memory() { return dev_mem; }

        /// \brief Return the offset of a buffer (may throw if no memory)
        size_t _get_buffer_offset(size_t buffer_index) const { return buffers_offsets.at(buffer_index); }

        /// \brief Map the buffer to host memory
        /// \note The bound memory MUST be host visible
        void *_map_buffer(size_t buffer_index) const { return dev_mem->map_memory(buffers_offsets.at(buffer_index), buffers[buffer_index].size()); }

        /// \brief Transfer some data to a buffer (using a batch transfer utility)
        /// \param signal_semaphore If specified, a semaphore that will become signaled when the transfer as been completed
        void transfer_data(batch_transfers &bt, size_t buffer_index, size_t data_size, const void *_data, vk::semaphore *signal_semaphore = nullptr, vk::fence *signal_fence = nullptr)
        {
          transfer_data(bt, buffer_index, 0, data_size, _data, signal_semaphore, signal_fence);
        }

        /// \brief Transfer some data to a buffer (using a batch transfer utility)
        /// \param signal_semaphore If specified, a semaphore that will become signaled when the transfer as been completed
        void transfer_data(batch_transfers &bt, size_t buffer_index, size_t offset, size_t data_size, const void *_data, vk::semaphore *signal_semaphore = nullptr, vk::fence *signal_fence = nullptr)
        {
          bt.add_transfer(buffers.at(buffer_index), offset, data_size, _data, signal_semaphore, signal_fence);
        }

        /// \brief Call this to setup the vertex description
        /// \see get_vertex_input_state()
        void setup_vertex_description(vk::pipeline_creator &pc)
        {
          pc.get_vertex_input_state() = pvis;
          pc.get_input_assembly_state().set_topology(topology).enable_primitive_restart(primitive_restart);
        }

        /// \brief Bind the buffers to a command buffer
        void bind(vk::command_buffer_recorder &cbr) const
        {
          std::vector<const vk::buffer *> vct_buf;
          vct_buf.reserve(buffers.size());
          if (index_buffer_present)
            cbr.bind_index_buffer(buffers[0], index_type);
          for (size_t i = (index_buffer_present ? 1 : 0); i < buffers.size(); ++i)
            vct_buf.push_back(&buffers[i]);
          cbr.bind_vertex_buffers(first_binding, vct_buf);
        }

      public:
        /// \brief Return the buffers. If there's an index buffer, it has index 0
        /// \note marked as advanced
        std::deque<vk::buffer> &_get_buffers() { return buffers; }

      protected:
        vk::device &dev;

        VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
        bool primitive_restart = false;

        std::deque<vk::buffer> buffers; // If there's an index buffer, it's the first one

        size_t first_binding = 0;
        VkIndexType index_type = VK_INDEX_TYPE_UINT16;

        std::deque<size_t> buffers_offsets;
        memory_allocation allocation;
        const vk::device_memory *dev_mem = nullptr;

        bool index_buffer_present = false;

        vk::pipeline_vertex_input_state pvis;
    };
  } // namespace hydra
} // namespace neam

#endif // __N_30181263603267010772_2083712051_MESH_HPP__

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexSimpleEntryContext.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:07:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLINDEXSIMPLEENTRYCONTEXT_HXX_
#include "XMLIndexSimpleEntryContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXTEMPLATECONTEXT_HXX_
#include "XMLIndexTemplateContext.hxx"
#endif

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_TEXTIMP_HXX_
#include "txtimp.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

//using namespace ::com::sun::star::text;

using ::rtl::OUString;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::PropertyValues;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Any;
using ::com::sun::star::xml::sax::XAttributeList;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_STYLE_NAME;

const sal_Char sAPI_TokenType[] = "TokenType";
const sal_Char sAPI_CharacterStyleName[] = "CharacterStyleName";

TYPEINIT1( XMLIndexSimpleEntryContext, SvXMLImportContext);

XMLIndexSimpleEntryContext::XMLIndexSimpleEntryContext(
    SvXMLImport& rImport,
    const OUString& rEntry,
    XMLIndexTemplateContext& rTemplate,
    sal_uInt16 nPrfx,
    const OUString& rLocalName ) :
        SvXMLImportContext(rImport, nPrfx, rLocalName),
        rTemplateContext(rTemplate),
        rEntryType(rEntry),
        sCharStyleName(),
        bCharStyleNameOK(sal_False),
        nValues(1)
{
}

XMLIndexSimpleEntryContext::~XMLIndexSimpleEntryContext()
{
}

void XMLIndexSimpleEntryContext::StartElement(
    const Reference<XAttributeList> & xAttrList)
{
    // we know only one attribute: style-name
    sal_Int16 nLength = xAttrList->getLength();
    for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
    {
        OUString sLocalName;
        sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
            GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
                              &sLocalName );
        if ( (XML_NAMESPACE_TEXT == nPrefix) &&
             IsXMLToken(sLocalName, XML_STYLE_NAME) )
        {
            sCharStyleName = xAttrList->getValueByIndex(nAttr);
            bCharStyleNameOK = sal_True;
        }
    }

    // if we have a style name, set it!
    if (bCharStyleNameOK)
    {
        nValues++;
    }

}

void XMLIndexSimpleEntryContext::EndElement()
{
    Sequence<PropertyValue> aValues(nValues);

    FillPropertyValues(aValues);
    rTemplateContext.addTemplateEntry(aValues);
}

void XMLIndexSimpleEntryContext::FillPropertyValues(
    ::com::sun::star::uno::Sequence<
        ::com::sun::star::beans::PropertyValue> & rValues)
{
    // due to the limited number of subclasses, we fill the values
    // directly into the slots. Subclasses will have to know they can
    // only use slot so-and-so.

    Any aAny;

    // token type
    rValues[0].Name = rTemplateContext.sTokenType;
    aAny <<= rEntryType;
    rValues[0].Value = aAny;

    // char style
    if (bCharStyleNameOK)
    {
        rValues[1].Name = rTemplateContext.sCharacterStyleName;
        aAny <<= GetImport().GetStyleDisplayName(
                                    XML_STYLE_FAMILY_TEXT_TEXT,
                                    sCharStyleName );
        rValues[1].Value = aAny;
    }

}
<commit_msg>INTEGRATION: CWS warnings01 (1.5.32); FILE MERGED 2005/11/03 17:47:08 cl 1.5.32.1: warning free code changes for unxlngi6<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexSimpleEntryContext.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 18:40:35 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLINDEXSIMPLEENTRYCONTEXT_HXX_
#include "XMLIndexSimpleEntryContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXTEMPLATECONTEXT_HXX_
#include "XMLIndexTemplateContext.hxx"
#endif

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_TEXTIMP_HXX_
#include "txtimp.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

//using namespace ::com::sun::star::text;

using ::rtl::OUString;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::PropertyValues;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Any;
using ::com::sun::star::xml::sax::XAttributeList;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_STYLE_NAME;

const sal_Char sAPI_TokenType[] = "TokenType";
const sal_Char sAPI_CharacterStyleName[] = "CharacterStyleName";

TYPEINIT1( XMLIndexSimpleEntryContext, SvXMLImportContext);

XMLIndexSimpleEntryContext::XMLIndexSimpleEntryContext(
    SvXMLImport& rImport,
    const OUString& rEntry,
    XMLIndexTemplateContext& rTemplate,
    sal_uInt16 nPrfx,
    const OUString& rLocalName )
:   SvXMLImportContext(rImport, nPrfx, rLocalName)
,   rEntryType(rEntry)
,   bCharStyleNameOK(sal_False)
,   rTemplateContext(rTemplate)
,   nValues(1)
{
}

XMLIndexSimpleEntryContext::~XMLIndexSimpleEntryContext()
{
}

void XMLIndexSimpleEntryContext::StartElement(
    const Reference<XAttributeList> & xAttrList)
{
    // we know only one attribute: style-name
    sal_Int16 nLength = xAttrList->getLength();
    for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
    {
        OUString sLocalName;
        sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
            GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
                              &sLocalName );
        if ( (XML_NAMESPACE_TEXT == nPrefix) &&
             IsXMLToken(sLocalName, XML_STYLE_NAME) )
        {
            sCharStyleName = xAttrList->getValueByIndex(nAttr);
            bCharStyleNameOK = sal_True;
        }
    }

    // if we have a style name, set it!
    if (bCharStyleNameOK)
    {
        nValues++;
    }

}

void XMLIndexSimpleEntryContext::EndElement()
{
    Sequence<PropertyValue> aValues(nValues);

    FillPropertyValues(aValues);
    rTemplateContext.addTemplateEntry(aValues);
}

void XMLIndexSimpleEntryContext::FillPropertyValues(
    ::com::sun::star::uno::Sequence<
        ::com::sun::star::beans::PropertyValue> & rValues)
{
    // due to the limited number of subclasses, we fill the values
    // directly into the slots. Subclasses will have to know they can
    // only use slot so-and-so.

    Any aAny;

    // token type
    rValues[0].Name = rTemplateContext.sTokenType;
    aAny <<= rEntryType;
    rValues[0].Value = aAny;

    // char style
    if (bCharStyleNameOK)
    {
        rValues[1].Name = rTemplateContext.sCharacterStyleName;
        aAny <<= GetImport().GetStyleDisplayName(
                                    XML_STYLE_FAMILY_TEXT_TEXT,
                                    sCharStyleName );
        rValues[1].Value = aAny;
    }

}
<|endoftext|>