<commit_before>/**
 Copyright 2015 Joachim Wolff
 Master Project
 Tutors: Milad Miladi, Fabrizio Costa
 Summer semester 2015

 Chair of Bioinformatics
 Department of Computer Science
 Faculty of Engineering
 Albert-Ludwig-University Freiburg im Breisgau
**/
#include <Python.h>
#include <math.h>

#ifdef OPENMP
#include <omp.h>
#endif
#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <iterator>
const int MAX_VALUE = 2147483647;
const double A = sqrt(2) - 1;

// Return an hash value for a given key in defined range aModulo
 int _intHashSimple(int key, int aModulo) {
    key = ~key + (key << 15);
    key = key ^ (key >> 12);
    key = key + (key << 2);
    key = key ^ (key >> 4);
    key = key * 2057;
    key = key ^ (key >> 16);
    return key % aModulo;
}
// compute the signature for one instance given the number of hash functions, the feature ids and a block size
std::vector< std::vector<int> > _computeSignature(const int numberOfHashFunctions,
                            const std::vector< std::vector<int> >& instanceFeatureVector, const int blockSize,
                            const int numberOfCores, int chunkSize) {

    const int sizeOfInstances = instanceFeatureVector.size();
    std::vector< std::vector<int> > instanceSignature;
    instanceSignature.resize(sizeOfInstances);
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
#pragma omp parallel for //schedule(static, chunkSize) num_threads(numberOfCores)
    for (int k = 0; k < sizeOfInstances; ++k) {
        const int sizeOfFeatureVector = instanceFeatureVector[k].size();
        std::vector<int> signatureHash(numberOfHashFunctions);
        for(int i = 0; i < numberOfHashFunctions; ++i) {
            int minHashValue = MAX_VALUE;
            for(int j = 0; j < sizeOfFeatureVector; ++j) {
                int hashValue = _intHashSimple((instanceFeatureVector[k][j]+1) * (i+1) * A, MAX_VALUE);
                if (hashValue == 0 || hashValue == MAX_VALUE) {
                    continue;
                }
                if (hashValue < minHashValue) {
                    minHashValue = hashValue;
                }
            }
            signatureHash[i] = minHashValue;
        }
        // reduce number of hash values by a factor of blockSize
        std::vector<int> signature;
        signature.reserve((numberOfHashFunctions / blockSize) + 1);
        int i = 0;
        while (i < (numberOfHashFunctions - blockSize)) {
            // use computed hash value as a seed for the next computation
            int signatureBlockValue = signatureHash[i];
            for (int j = 0; j < blockSize; ++j){
                signatureBlockValue = _intHashSimple((signatureHash[i+j]) * signatureBlockValue * A, MAX_VALUE);
            }
            signature.push_back(signatureBlockValue);
            i += blockSize;
        }
//#pragma omp critical
        instanceSignature[k] = signature;
    }
    return instanceSignature;
}
// compute the complete inverse index for all given instances and theire non null features
std::vector<std::map<int, std::vector<int> > >  _computeInverseIndex(const int numberOfHashFunctions,
                                                                std::map<int, std::vector<int> >& instance_featureVector,
                                                                const int blockSize, const int maxBinSize, const int numberOfCores, int chunkSize) {

    std::vector<std::map<int, std::vector<int> > > inverseIndex;
    int inverseIndexSize = ceil(((float) numberOfHashFunctions / (float) blockSize)+1);
    inverseIndex.resize(inverseIndexSize);
    if (chunkSize == -1) {
        int chunkSize = ceil(instance_featureVector.size() / numberOfCores);
    } else if(chunkSize == 0) {
        chunkSize = numberOfCores;
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
#pragma omp parallel for //schedule(static, chunkSize) num_threads(numberOfCores)
    for(int index = 0; index < instance_featureVector.size(); ++index){

        std::map<int, std::vector<int> >::iterator instanceId = instance_featureVector.begin();
        std::advance(instanceId, index);

        std::map<int, std::vector<int> >::iterator itHashValue_InstanceVector;
        std::vector<std::map<int, int> > hashStorage;
        std::vector<int> signatureHash(numberOfHashFunctions);
        // for every hash function: compute the hash values of all features and take the minimum of these
        // as the hash value for one hash function --> h_j(x) = argmin (x_i of x) f_j(x_i)
        for(int j = 0; j < numberOfHashFunctions; ++j) {
            int minHashValue = MAX_VALUE;
            for (std::vector<int>::iterator itFeatures = instanceId->second.begin(); itFeatures != instanceId->second.end(); ++itFeatures) {
                int hashValue = _intHashSimple((*itFeatures +1) * (j+1) * A, MAX_VALUE);
                if (hashValue < minHashValue) {
                    minHashValue = hashValue;
                }
            }
            signatureHash[j] = minHashValue;
        }
        // reduce number of hash values by a factor of blockSize
        int k = 0;
        std::vector<int> signature;
        signature.reserve((numberOfHashFunctions / blockSize) + 1);
        while (k < (numberOfHashFunctions)) {
            // use computed hash value as a seed for the next computation
            int signatureBlockValue = signatureHash[k];
            for (int j = 0; j < blockSize; ++j) {
                signatureBlockValue = _intHashSimple((signatureHash[k+j]) * signatureBlockValue * A, MAX_VALUE);
            }
            signature.push_back(signatureBlockValue);
            k += blockSize;
        }

        // insert in inverse index
#pragma omp critical
        for (int j = 0; j < signature.size(); ++j) {
            itHashValue_InstanceVector = inverseIndex[j].find(signature[j]);
            // if for hash function h_i() the given hash values is already stored
            if (itHashValue_InstanceVector != inverseIndex[j].end()) {
                // insert the instance id if not too many collisions (maxBinSize)
                if (itHashValue_InstanceVector->second.size() < maxBinSize) {
                    // insert only if there wasn't too any collisions in the past
                    if (itHashValue_InstanceVector->second.size() > 0 && itHashValue_InstanceVector->second[0] != -1) {
                        itHashValue_InstanceVector->second.push_back(instanceId->first);
                    }
                } else {
                    // too many collisions: delete stored ids and set it to error value -1
                    itHashValue_InstanceVector->second.clear();
                    itHashValue_InstanceVector->second.push_back(-1);
                }
            } else {
                // given hash value for the specific hash function was not avaible: insert new hash value
                std::vector<int> instanceIdVector;
                instanceIdVector.push_back(instanceId->first);
                inverseIndex[j][signature[j]] = instanceIdVector;
            }
        }
    }
    return inverseIndex;
}

// parse python call to c++; execute c++ and parse it back to python
static PyObject* computeIntHash(PyObject* self, PyObject* args)
{
    int key, modulo, seed;

    if (!PyArg_ParseTuple(args, "iii", &key, &modulo, &seed))
        return NULL;

    return Py_BuildValue("i",   _intHashSimple(key * (seed + 1) * A, modulo));
}

// parse python call to c++; execute c++ and parse it back to python
static PyObject* computeInverseIndex(PyObject* self, PyObject* args)
{
    int numberOfHashFunctions, blockSize, maxBinSize, numberOfCores, chunkSize;
    std::map<int, std::vector<int> > instance_featureVector;
    PyObject * instancesListObj;
    PyObject * featuresListObj;
    PyObject * instanceIntObj;
    PyObject * featureIntObj;

    if (!PyArg_ParseTuple(args, "iO!O!iiii", &numberOfHashFunctions, &PyList_Type, &instancesListObj, &PyList_Type,
                            &featuresListObj, &blockSize, &maxBinSize, &numberOfCores, &chunkSize))
        return NULL;
    //std::cout << "Number of cors: " << numberOfCores;
    int sizeOfFeatureVector = PyList_Size(instancesListObj);
    if (sizeOfFeatureVector < 0)	return NULL;
    int instanceOld = -1;
    int insert = 0;
    std::vector<int> featureIds;
    // parse from python list to a c++ map<int, vector<int> >
    // where key == instance id and vector<int> == non null feature ids
    for (int i = 0; i < sizeOfFeatureVector; ++i) {
        instanceIntObj = PyList_GetItem(instancesListObj, i);
        featureIntObj = PyList_GetItem(featuresListObj, i);
        int featureValue;
        int instanceValue;

        PyArg_Parse(instanceIntObj, "i", &instanceValue);
        PyArg_Parse(featureIntObj, "i", &featureValue);

        if (instanceOld == instanceValue) {
            featureIds.push_back(featureValue);
            instanceOld = instanceValue;
            if (i == sizeOfFeatureVector-1) {
                instance_featureVector[instanceValue] = featureIds;
            }
        } else {
            if (instanceOld != -1 ) {
                instance_featureVector[instanceOld] = featureIds;
            }
            featureIds.clear();
            featureIds.push_back(featureValue);
            instanceOld = instanceValue;
        }
    }
    // compute inverse index in c++
    std::vector<std::map<int, std::vector<int> > > inverseIndex = _computeInverseIndex(numberOfHashFunctions, instance_featureVector,
                                     blockSize, maxBinSize, numberOfCores, chunkSize);

    int sizeOfInverseIndex = inverseIndex.size();
    PyObject * outListObj = PyList_New(sizeOfInverseIndex);
    // parse c++ map<int, vector<int> > to python list[dict{hash_value: [featureIds]}]
    // Iterate over every hash function
    for (int i = 0; i < sizeOfInverseIndex; ++i) {
        PyObject* dictionary = PyDict_New();
        // iterate over every hash value
        for (std::map<int, std::vector<int> >::iterator it = inverseIndex[i].begin(); it != inverseIndex[i].end(); ++it) {
            PyObject* list = PyList_New(it->second.size());
            // get all indicies for this hash value
            for (int j = 0; j < it->second.size(); ++j) {
                PyObject* value = Py_BuildValue("i", it->second[j]);
                PyObject* PyListIndexLocal = Py_BuildValue("i", j);
                Py_ssize_t listIndexLocal = PyInt_AsSsize_t(PyListIndexLocal);

                PyList_SetItem(list, listIndexLocal, value);
            }
            PyObject* key = Py_BuildValue("i", it->first);
            PyDict_SetItem(dictionary, key, list);
        }
        PyObject* PyListIndex = Py_BuildValue("i", i);
        Py_ssize_t listIndex = PyInt_AsSsize_t(PyListIndex);

        if (PyList_SetItem(outListObj, listIndex, dictionary) == -1) {
            std::cout << "Failure!" << std::flush;
        }
    }
    return outListObj;
}
// parse python call to c++; execute c++ and parse it back to python
static PyObject* computeSignature(PyObject* self, PyObject* args)
{
    int numberOfHashFunctions, blockSize, numberOfCores, chunkSize;
    std::vector< std::vector<int> > instanceFeatureVector;

    PyObject * listInstancesObj;
    PyObject * listFeaturesObj;
    PyObject * listObjFeature;
    PyObject * intInstancesObj;
    PyObject * intFeaturesObj;
    int instanceOld = -1;

    if (!PyArg_ParseTuple(args, "iO!O!iii", &numberOfHashFunctions,
                        &PyList_Type, &listInstancesObj,
                        &PyList_Type, &listFeaturesObj, &blockSize, &numberOfCores, &chunkSize))
        return NULL;

    int numLinesInstances = PyList_Size(listInstancesObj);
    if (numLinesInstances < 0)	return NULL;

    int numLinesFeatures = PyList_Size(listFeaturesObj);
    if (numLinesFeatures < 0)	return NULL;

    int insert = 0;
    std::vector<int> featureIds;
   // std::cout << "BEvor trans" << std::endl << std::flush;
    // parse from python list to c++ vector
    for (int i = 0; i < numLinesInstances; ++i) {
        intInstancesObj = PyList_GetItem(listInstancesObj, i);
        intFeaturesObj = PyList_GetItem(listFeaturesObj, i);
        int featureValue;
        int instanceValue;

        PyArg_Parse(intInstancesObj, "i", &instanceValue);
        PyArg_Parse(intFeaturesObj, "i", &featureValue);

        if (instanceOld == instanceValue) {
            featureIds.push_back(featureValue);
            instanceOld = instanceValue;
            if (i == numLinesInstances-1) {
                instanceFeatureVector.push_back(featureIds);
            }
        } else {
            if (instanceOld != -1 ) {
                instanceFeatureVector.push_back(featureIds);
            }
            featureIds.clear();
//            instanceFeatureVector.push_back(featureIds);
            instanceOld = instanceValue;
        }
    }
  //  std::cout << "After trans" << std::endl << std::flush;
    std::cout << "InstanceFeaturVector: " << std::endl << std::flush;
//    for (int i = 0; i <5; i++) {
//        for (int j = 0; j < instanceFeatureVector[i].size(); j++) {
//            std::cout << instanceFeatureVector[i][j] << " "<< std::flush;
//        }
//         std::cout << "\nNewLine: " << std::endl << std::flush;
//
//    }
    // compute in c++
    std::vector< std::vector<int> >signatures = _computeSignature(numberOfHashFunctions, instanceFeatureVector,
                                                                                blockSize,numberOfCores, chunkSize);
   // std::cout << "After comput" << std::endl << std::flush;

    // parse from c++ vector to python list

    int sizeOfSignature = signatures.size();
    PyObject * outListInstancesObj = PyList_New(sizeOfSignature);
    for (int i = 0; i < sizeOfSignature; ++i) {
    int sizeOfFeature = signatures[i].size();
        PyObject * outListFeaturesObj = PyList_New(sizeOfFeature);
        for (int j = 0; j < sizeOfFeature; ++j) {
            PyObject* value = Py_BuildValue("i", signatures[i][j]);
            PyList_SetItem(outListFeaturesObj, j, value);
        }
        PyList_SetItem(outListInstancesObj, i, outListFeaturesObj);
    }

    return outListInstancesObj;
}
// definition of avaible functions for python and which function parsing fucntion in c++ should be called.
static PyMethodDef IntHashMethods[] = {
    {"computeIntHash", computeIntHash, METH_VARARGS, "Calculate a hash for given key, modulo and seed."},
    {"computeSignature", computeSignature, METH_VARARGS, "Calculate a signature for a given instance."},
    {"computeInverseIndex", computeInverseIndex, METH_VARARGS, "Calculate the inverse index for the given instances."},

    {NULL, NULL, 0, NULL}
};

// definition of the module for python
PyMODINIT_FUNC
init_hashUtility(void)
{
    (void) Py_InitModule("_hashUtility", IntHashMethods);
}
<commit_msg>Bug fixing.<commit_after>/**
 Copyright 2015 Joachim Wolff
 Master Project
 Tutors: Milad Miladi, Fabrizio Costa
 Summer semester 2015

 Chair of Bioinformatics
 Department of Computer Science
 Faculty of Engineering
 Albert-Ludwig-University Freiburg im Breisgau
**/
#include <Python.h>
#include <math.h>

#ifdef OPENMP
#include <omp.h>
#endif
#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <iterator>
const int MAX_VALUE = 2147483647;
const double A = sqrt(2) - 1;

// Return an hash value for a given key in defined range aModulo
 int _intHashSimple(int key, int aModulo) {
    key = ~key + (key << 15);
    key = key ^ (key >> 12);
    key = key + (key << 2);
    key = key ^ (key >> 4);
    key = key * 2057;
    key = key ^ (key >> 16);
    return key % aModulo;
}
// compute the signature for one instance given the number of hash functions, the feature ids and a block size
std::vector< std::vector<int> > _computeSignature(const int numberOfHashFunctions,
                            const std::vector< std::vector<int> >& instanceFeatureVector, const int blockSize,
                            const int numberOfCores, int chunkSize) {

    const int sizeOfInstances = instanceFeatureVector.size();
    std::vector< std::vector<int> > instanceSignature;
    instanceSignature.resize(sizeOfInstances);
    if (chunkSize <= 0) {
        chunkSize = ceil(instanceFeatureVector.size() / static_cast<float>(numberOfCores));
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
#pragma omp parallel for schedule(static, chunkSize) num_threads(numberOfCores)
    for (int k = 0; k < sizeOfInstances; ++k) {
        const int sizeOfFeatureVector = instanceFeatureVector[k].size();
        std::vector<int> signatureHash(numberOfHashFunctions);
        for(int i = 0; i < numberOfHashFunctions; ++i) {
            int minHashValue = MAX_VALUE;
            for(int j = 0; j < sizeOfFeatureVector; ++j) {
                int hashValue = _intHashSimple((instanceFeatureVector[k][j]+1) * (i+1) * A, MAX_VALUE);
                if (hashValue == 0 || hashValue == MAX_VALUE) {
                    continue;
                }
                if (hashValue < minHashValue) {
                    minHashValue = hashValue;
                }
            }
            signatureHash[i] = minHashValue;
        }
        // reduce number of hash values by a factor of blockSize
        std::vector<int> signature;
        signature.reserve((numberOfHashFunctions / blockSize) + 1);
        int i = 0;
        while (i < (numberOfHashFunctions - blockSize)) {
            // use computed hash value as a seed for the next computation
            int signatureBlockValue = signatureHash[i];
            for (int j = 0; j < blockSize; ++j){
                signatureBlockValue = _intHashSimple((signatureHash[i+j]) * signatureBlockValue * A, MAX_VALUE);
            }
            signature.push_back(signatureBlockValue);
            i += blockSize;
        }
//#pragma omp critical
        instanceSignature[k] = signature;
    }
    return instanceSignature;
}
// compute the complete inverse index for all given instances and theire non null features
std::vector<std::map<int, std::vector<int> > >  _computeInverseIndex(const int numberOfHashFunctions,
                                                                std::map<int, std::vector<int> >& instance_featureVector,
                                                                const int blockSize, const int maxBinSize, const int numberOfCores, int chunkSize) {

    std::vector<std::map<int, std::vector<int> > > inverseIndex;
    int inverseIndexSize = ceil(((float) numberOfHashFunctions / (float) blockSize)+1);
    inverseIndex.resize(inverseIndexSize);
    if (chunkSize <= 0) {
        chunkSize = ceil(instance_featureVector.size() / static_cast<float>(numberOfCores));
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
#pragma omp parallel for schedule(static, chunkSize) num_threads(numberOfCores)
    for(int index = 0; index < instance_featureVector.size(); ++index){

        std::map<int, std::vector<int> >::iterator instanceId = instance_featureVector.begin();
        std::advance(instanceId, index);

        std::map<int, std::vector<int> >::iterator itHashValue_InstanceVector;
        std::vector<std::map<int, int> > hashStorage;
        std::vector<int> signatureHash(numberOfHashFunctions);
        // for every hash function: compute the hash values of all features and take the minimum of these
        // as the hash value for one hash function --> h_j(x) = argmin (x_i of x) f_j(x_i)
        for(int j = 0; j < numberOfHashFunctions; ++j) {
            int minHashValue = MAX_VALUE;
            for (std::vector<int>::iterator itFeatures = instanceId->second.begin(); itFeatures != instanceId->second.end(); ++itFeatures) {
                int hashValue = _intHashSimple((*itFeatures +1) * (j+1) * A, MAX_VALUE);
                if (hashValue < minHashValue) {
                    minHashValue = hashValue;
                }
            }
            signatureHash[j] = minHashValue;
        }
        // reduce number of hash values by a factor of blockSize
        int k = 0;
        std::vector<int> signature;
        signature.reserve((numberOfHashFunctions / blockSize) + 1);
        while (k < (numberOfHashFunctions)) {
            // use computed hash value as a seed for the next computation
            int signatureBlockValue = signatureHash[k];
            for (int j = 0; j < blockSize; ++j) {
                signatureBlockValue = _intHashSimple((signatureHash[k+j]) * signatureBlockValue * A, MAX_VALUE);
            }
            signature.push_back(signatureBlockValue);
            k += blockSize;
        }

        // insert in inverse index
#pragma omp critical
        for (int j = 0; j < signature.size(); ++j) {
            itHashValue_InstanceVector = inverseIndex[j].find(signature[j]);
            // if for hash function h_i() the given hash values is already stored
            if (itHashValue_InstanceVector != inverseIndex[j].end()) {
                // insert the instance id if not too many collisions (maxBinSize)
                if (itHashValue_InstanceVector->second.size() < maxBinSize) {
                    // insert only if there wasn't too any collisions in the past
                    if (itHashValue_InstanceVector->second.size() > 0 && itHashValue_InstanceVector->second[0] != -1) {
                        itHashValue_InstanceVector->second.push_back(instanceId->first);
                    }
                } else {
                    // too many collisions: delete stored ids and set it to error value -1
                    itHashValue_InstanceVector->second.clear();
                    itHashValue_InstanceVector->second.push_back(-1);
                }
            } else {
                // given hash value for the specific hash function was not avaible: insert new hash value
                std::vector<int> instanceIdVector;
                instanceIdVector.push_back(instanceId->first);
                inverseIndex[j][signature[j]] = instanceIdVector;
            }
        }
    }
    return inverseIndex;
}

// parse python call to c++; execute c++ and parse it back to python
static PyObject* computeIntHash(PyObject* self, PyObject* args)
{
    int key, modulo, seed;

    if (!PyArg_ParseTuple(args, "iii", &key, &modulo, &seed))
        return NULL;

    return Py_BuildValue("i",   _intHashSimple(key * (seed + 1) * A, modulo));
}

// parse python call to c++; execute c++ and parse it back to python
static PyObject* computeInverseIndex(PyObject* self, PyObject* args)
{
    int numberOfHashFunctions, blockSize, maxBinSize, numberOfCores, chunkSize;
    std::map<int, std::vector<int> > instance_featureVector;
    PyObject * instancesListObj;
    PyObject * featuresListObj;
    PyObject * instanceIntObj;
    PyObject * featureIntObj;

    if (!PyArg_ParseTuple(args, "iO!O!iiii", &numberOfHashFunctions, &PyList_Type, &instancesListObj, &PyList_Type,
                            &featuresListObj, &blockSize, &maxBinSize, &numberOfCores, &chunkSize))
        return NULL;
    //std::cout << "Number of cors: " << numberOfCores;
    int sizeOfFeatureVector = PyList_Size(instancesListObj);
    if (sizeOfFeatureVector < 0)	return NULL;
    int instanceOld = -1;
    int insert = 0;
    std::vector<int> featureIds;
    // parse from python list to a c++ map<int, vector<int> >
    // where key == instance id and vector<int> == non null feature ids
    for (int i = 0; i < sizeOfFeatureVector; ++i) {
        instanceIntObj = PyList_GetItem(instancesListObj, i);
        featureIntObj = PyList_GetItem(featuresListObj, i);
        int featureValue;
        int instanceValue;

        PyArg_Parse(instanceIntObj, "i", &instanceValue);
        PyArg_Parse(featureIntObj, "i", &featureValue);

        if (instanceOld == instanceValue) {
            featureIds.push_back(featureValue);
            instanceOld = instanceValue;
            if (i == sizeOfFeatureVector-1) {
                instance_featureVector[instanceValue] = featureIds;
            }
        } else {
            if (instanceOld != -1 ) {
                instance_featureVector[instanceOld] = featureIds;
            }
            featureIds.clear();
            featureIds.push_back(featureValue);
            instanceOld = instanceValue;
        }
    }
    // compute inverse index in c++
    std::vector<std::map<int, std::vector<int> > > inverseIndex = _computeInverseIndex(numberOfHashFunctions, instance_featureVector,
                                     blockSize, maxBinSize, numberOfCores, chunkSize);

    int sizeOfInverseIndex = inverseIndex.size();
    PyObject * outListObj = PyList_New(sizeOfInverseIndex);
    // parse c++ map<int, vector<int> > to python list[dict{hash_value: [featureIds]}]
    // Iterate over every hash function
    for (int i = 0; i < sizeOfInverseIndex; ++i) {
        PyObject* dictionary = PyDict_New();
        // iterate over every hash value
        for (std::map<int, std::vector<int> >::iterator it = inverseIndex[i].begin(); it != inverseIndex[i].end(); ++it) {
            PyObject* list = PyList_New(it->second.size());
            // get all indicies for this hash value
            for (int j = 0; j < it->second.size(); ++j) {
                PyObject* value = Py_BuildValue("i", it->second[j]);
                PyObject* PyListIndexLocal = Py_BuildValue("i", j);
                Py_ssize_t listIndexLocal = PyInt_AsSsize_t(PyListIndexLocal);

                PyList_SetItem(list, listIndexLocal, value);
            }
            PyObject* key = Py_BuildValue("i", it->first);
            PyDict_SetItem(dictionary, key, list);
        }
        PyObject* PyListIndex = Py_BuildValue("i", i);
        Py_ssize_t listIndex = PyInt_AsSsize_t(PyListIndex);

        if (PyList_SetItem(outListObj, listIndex, dictionary) == -1) {
            std::cout << "Failure!" << std::flush;
        }
    }
    return outListObj;
}
// parse python call to c++; execute c++ and parse it back to python
static PyObject* computeSignature(PyObject* self, PyObject* args)
{
    int numberOfHashFunctions, blockSize, numberOfCores, chunkSize;
    std::vector< std::vector<int> > instanceFeatureVector;

    PyObject * listInstancesObj;
    PyObject * listFeaturesObj;
    PyObject * listObjFeature;
    PyObject * intInstancesObj;
    PyObject * intFeaturesObj;
    int instanceOld = -1;

    if (!PyArg_ParseTuple(args, "iO!O!iii", &numberOfHashFunctions,
                        &PyList_Type, &listInstancesObj,
                        &PyList_Type, &listFeaturesObj, &blockSize, &numberOfCores, &chunkSize))
        return NULL;

    int numLinesInstances = PyList_Size(listInstancesObj);
    if (numLinesInstances < 0)	return NULL;

    int numLinesFeatures = PyList_Size(listFeaturesObj);
    if (numLinesFeatures < 0)	return NULL;

    int insert = 0;
    std::vector<int> featureIds;
   // std::cout << "BEvor trans" << std::endl << std::flush;
    // parse from python list to c++ vector
    for (int i = 0; i < numLinesInstances; ++i) {
        intInstancesObj = PyList_GetItem(listInstancesObj, i);
        intFeaturesObj = PyList_GetItem(listFeaturesObj, i);
        int featureValue;
        int instanceValue;

        PyArg_Parse(intInstancesObj, "i", &instanceValue);
        PyArg_Parse(intFeaturesObj, "i", &featureValue);

        if (instanceOld == instanceValue) {
            featureIds.push_back(featureValue);
            instanceOld = instanceValue;
            if (i == numLinesInstances-1) {
                instanceFeatureVector.push_back(featureIds);
            }
        } else {
            if (instanceOld != -1 ) {
                instanceFeatureVector.push_back(featureIds);
            }
            featureIds.clear();
//            instanceFeatureVector.push_back(featureIds);
            instanceOld = instanceValue;
        }
    }
  //  std::cout << "After trans" << std::endl << std::flush;
    std::cout << "InstanceFeaturVector: " << std::endl << std::flush;
//    for (int i = 0; i <5; i++) {
//        for (int j = 0; j < instanceFeatureVector[i].size(); j++) {
//            std::cout << instanceFeatureVector[i][j] << " "<< std::flush;
//        }
//         std::cout << "\nNewLine: " << std::endl << std::flush;
//
//    }
    // compute in c++
    std::vector< std::vector<int> >signatures = _computeSignature(numberOfHashFunctions, instanceFeatureVector,
                                                                                blockSize,numberOfCores, chunkSize);
   // std::cout << "After comput" << std::endl << std::flush;

    // parse from c++ vector to python list

    int sizeOfSignature = signatures.size();
    PyObject * outListInstancesObj = PyList_New(sizeOfSignature);
    for (int i = 0; i < sizeOfSignature; ++i) {
    int sizeOfFeature = signatures[i].size();
        PyObject * outListFeaturesObj = PyList_New(sizeOfFeature);
        for (int j = 0; j < sizeOfFeature; ++j) {
            PyObject* value = Py_BuildValue("i", signatures[i][j]);
            PyList_SetItem(outListFeaturesObj, j, value);
        }
        PyList_SetItem(outListInstancesObj, i, outListFeaturesObj);
    }

    return outListInstancesObj;
}
// definition of avaible functions for python and which function parsing fucntion in c++ should be called.
static PyMethodDef IntHashMethods[] = {
    {"computeIntHash", computeIntHash, METH_VARARGS, "Calculate a hash for given key, modulo and seed."},
    {"computeSignature", computeSignature, METH_VARARGS, "Calculate a signature for a given instance."},
    {"computeInverseIndex", computeInverseIndex, METH_VARARGS, "Calculate the inverse index for the given instances."},

    {NULL, NULL, 0, NULL}
};

// definition of the module for python
PyMODINIT_FUNC
init_hashUtility(void)
{
    (void) Py_InitModule("_hashUtility", IntHashMethods);
}
<|endoftext|>


<commit_before>#ifndef KMC_KLANG_LEXICAL_ANALYSIS_HPP
#define KMC_KLANG_LEXICAL_ANALYSIS_HPP

#include <fstream>
#include <string>
#include <vector>

namespace klang {

enum class TokenType {
  IDENTIFIER,
  DIGIT,
  SYMBOL,
  INT,
  RETURN,
  EOF
};

class Token {
 public:
  Token();
  Token(TokenType type, const std::string& str, int line);
  TokenType type() const;
  std::string str() const;
  int number() const;
  int line() const;
 private:
  TokenType type_;
  std::string str_;
  int number_;
  int line_;
};

class TokenVector {
 public:
  bool unget_token(int times = 1);
  bool next_token();
  bool push_token(Token token);
  Token get_token() const;
  TokenType current_type() const;
  std::string current_string() const;
  int current_value() const;
  int current_index() const;
  bool set_index(int index);
  bool print_tokens() const;
 private:
  std::vector<Token> tokens_;
  int current_index_;
};

TokenVector LexicalAnalysis(std::ifstream& is);

}  // klang

#endif  // KMC_KLANG_LEXICAL_ANALYSIS_HPP
<commit_msg>トークンの情報を整理。<commit_after>#ifndef KMC_KLANG_LEXICAL_ANALYSIS_HPP
#define KMC_KLANG_LEXICAL_ANALYSIS_HPP

#include <fstream>
#include <string>
#include <vector>

namespace klang {

enum class TokenType {
  IDENTIFIER,
  DIGIT,
  RESERVED,
  CHARACTER,
  STRING
};

class Token {
 public:
  Token();
  Token(TokenType type, const std::string& str, int line);
  TokenType type() const;
  std::string str() const;
  int number() const;
  int line() const;
 private:
  TokenType type_;
  std::string str_;
  int number_;
  int line_;
};

class TokenVector {
 public:
  bool unget_token(int times = 1);
  bool next_token();
  bool push_token(Token token);
  Token get_token() const;
  TokenType current_type() const;
  std::string current_string() const;
  int current_value() const;
  int current_index() const;
  bool set_index(int index);
  bool print_tokens() const;
 private:
  std::vector<Token> tokens_;
  int current_index_;
};

TokenVector LexicalAnalysis(std::ifstream& is);

}  // klang

#endif  // KMC_KLANG_LEXICAL_ANALYSIS_HPP
<|endoftext|>


<commit_before>//===------- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements support for a bisecting optimizations based on a
/// command line option.
///
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
                                   cl::init(INT_MAX), cl::Optional,
                                   cl::desc("Maximum optimization to perform"));

OptBisect::OptBisect() {
  BisectEnabled = OptBisectLimit != INT_MAX;
}

static void printPassMessage(const StringRef &Name, int PassNum,
                             StringRef TargetDesc, bool Running) {
  StringRef Status = Running ? "" : "NOT ";
  errs() << "BISECT: " << Status << "running pass "
         << "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n";
}

static void printCaseMessage(int CaseNum, StringRef Msg, bool Running) {
  if (Running)
    errs() << "BISECT: running case (";
  else
    errs() << "BISECT: NOT running case (";
  errs() << CaseNum << "): " << Msg << "\n";
}

static std::string getDescription(const Module &M) {
  return "module (" + M.getName().str() + ")";
}

static std::string getDescription(const Function &F) {
  return "function (" + F.getName().str() + ")";
}

static std::string getDescription(const BasicBlock &BB) {
  return "basic block (" + BB.getName().str() + ") in function (" +
         BB.getParent()->getName().str() + ")";
}

static std::string getDescription(const Loop &L) {
  // FIXME: I'd like to be able to provide a better description here, but
  //        calling L->getHeader() would introduce a new dependency on the
  //        LLVMCore library.
  return "loop";
}

static std::string getDescription(const CallGraphSCC &SCC) {
  std::string Desc = "SCC (";
  bool First = true;
  for (CallGraphNode *CGN : SCC) {
    if (First)
      First = false;
    else
      Desc += ", ";
    Function *F = CGN->getFunction();
    if (F)
      Desc += F->getName();
    else
      Desc += "<<null function>>";
  }
  Desc += ")";
  return Desc;
}

static std::string getDescription(const LazyCallGraph::SCC &SCC) {
  std::string Desc = "SCC (";
  bool First = true;
  for (LazyCallGraph::Node &CGN : SCC) {
    if (First)
      First = false;
    else
      Desc += ", ";
    Function &F = CGN.getFunction();
    Desc += F.getName();
  }
  Desc += ")";
  return Desc;
}

// Force instantiations.
template bool OptBisect::shouldRunPass(const Pass *, const Module &);
template bool OptBisect::shouldRunPass(const Pass *, const Function &);
template bool OptBisect::shouldRunPass(const Pass *, const BasicBlock &);
template bool OptBisect::shouldRunPass(const Pass *, const Loop &);
template bool OptBisect::shouldRunPass(const Pass *, const CallGraphSCC &);

template <class UnitT>
bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) {
  if (!BisectEnabled)
    return true;
  return checkPass(P->getPassName(), getDescription(U));
}

bool OptBisect::checkPass(const StringRef PassName,
                          const StringRef TargetDesc) {
  assert(BisectEnabled);

  int CurBisectNum = ++LastBisectNum;
  bool ShouldRun = (OptBisectLimit == -1 || CurBisectNum <= OptBisectLimit);
  printPassMessage(PassName, CurBisectNum, TargetDesc, ShouldRun);
  return ShouldRun;
}

bool OptBisect::shouldRunCase(const Twine &Msg) {
  if (!BisectEnabled)
    return true;
  int CurFuelNum = ++LastBisectNum;
  bool ShouldRun = (OptBisectLimit == -1 || CurFuelNum <= OptBisectLimit);
  printCaseMessage(CurFuelNum, Msg.str(), ShouldRun);
  return ShouldRun;
}

<commit_msg>Removing unused function.<commit_after>//===------- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements support for a bisecting optimizations based on a
/// command line option.
///
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
                                   cl::init(INT_MAX), cl::Optional,
                                   cl::desc("Maximum optimization to perform"));

OptBisect::OptBisect() {
  BisectEnabled = OptBisectLimit != INT_MAX;
}

static void printPassMessage(const StringRef &Name, int PassNum,
                             StringRef TargetDesc, bool Running) {
  StringRef Status = Running ? "" : "NOT ";
  errs() << "BISECT: " << Status << "running pass "
         << "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n";
}

static void printCaseMessage(int CaseNum, StringRef Msg, bool Running) {
  if (Running)
    errs() << "BISECT: running case (";
  else
    errs() << "BISECT: NOT running case (";
  errs() << CaseNum << "): " << Msg << "\n";
}

static std::string getDescription(const Module &M) {
  return "module (" + M.getName().str() + ")";
}

static std::string getDescription(const Function &F) {
  return "function (" + F.getName().str() + ")";
}

static std::string getDescription(const BasicBlock &BB) {
  return "basic block (" + BB.getName().str() + ") in function (" +
         BB.getParent()->getName().str() + ")";
}

static std::string getDescription(const Loop &L) {
  // FIXME: I'd like to be able to provide a better description here, but
  //        calling L->getHeader() would introduce a new dependency on the
  //        LLVMCore library.
  return "loop";
}

static std::string getDescription(const CallGraphSCC &SCC) {
  std::string Desc = "SCC (";
  bool First = true;
  for (CallGraphNode *CGN : SCC) {
    if (First)
      First = false;
    else
      Desc += ", ";
    Function *F = CGN->getFunction();
    if (F)
      Desc += F->getName();
    else
      Desc += "<<null function>>";
  }
  Desc += ")";
  return Desc;
}

// Force instantiations.
template bool OptBisect::shouldRunPass(const Pass *, const Module &);
template bool OptBisect::shouldRunPass(const Pass *, const Function &);
template bool OptBisect::shouldRunPass(const Pass *, const BasicBlock &);
template bool OptBisect::shouldRunPass(const Pass *, const Loop &);
template bool OptBisect::shouldRunPass(const Pass *, const CallGraphSCC &);

template <class UnitT>
bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) {
  if (!BisectEnabled)
    return true;
  return checkPass(P->getPassName(), getDescription(U));
}

bool OptBisect::checkPass(const StringRef PassName,
                          const StringRef TargetDesc) {
  assert(BisectEnabled);

  int CurBisectNum = ++LastBisectNum;
  bool ShouldRun = (OptBisectLimit == -1 || CurBisectNum <= OptBisectLimit);
  printPassMessage(PassName, CurBisectNum, TargetDesc, ShouldRun);
  return ShouldRun;
}

bool OptBisect::shouldRunCase(const Twine &Msg) {
  if (!BisectEnabled)
    return true;
  int CurFuelNum = ++LastBisectNum;
  bool ShouldRun = (OptBisectLimit == -1 || CurFuelNum <= OptBisectLimit);
  printCaseMessage(CurFuelNum, Msg.str(), ShouldRun);
  return ShouldRun;
}

<|endoftext|>


<commit_before>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "TextureOGL.h"
#include "core/Engine.h"
#include "RendererOGL.h"
#include "graphics/Image.h"
#include "utils/Log.h"

namespace ouzel
{
    namespace graphics
    {
        TextureOGL::TextureOGL()
        {
        }

        TextureOGL::~TextureOGL()
        {
            if (textureId)
            {
                RendererOGL::deleteResource(textureId, RendererOGL::ResourceType::Texture);
            }
        }

        void TextureOGL::free()
        {
            Texture::free();

            if (textureId)
            {
                RendererOGL::deleteResource(textureId, RendererOGL::ResourceType::Texture);
                textureId = 0;
            }

            width = 0;
            height = 0;
        }

        bool TextureOGL::upload()
        {
            if (uploadData.dirty)
            {
                if (!textureId)
                {
                    glGenTextures(1, &textureId);

                    if (RendererOGL::checkOpenGLError())
                    {
                        Log(Log::Level::ERR) << "Failed to create texture";
                        return false;
                    }
                }

                if (!uploadData.levels.empty())
                {
                    RendererOGL::bindTexture(textureId, 0);

                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

                    RendererOGL* rendererOGL = static_cast<RendererOGL*>(sharedEngine->getRenderer());

                    if (uploadData.mipmaps) // has mip-maps
                    {
                        switch (rendererOGL->getTextureFilter())
                        {
                            case TextureFilter::NONE:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                                break;
                            case TextureFilter::LINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                                break;
                            case TextureFilter::BILINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                                break;
                            case TextureFilter::TRILINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                                break;
                        }
                    }
                    else
                    {
                        if (rendererOGL->getTextureFilter() == TextureFilter::NONE)
                        {
                            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                        }
                        else
                        {
                            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                        }
                    }

                    if (RendererOGL::checkOpenGLError())
                    {
                        Log(Log::Level::ERR) << "Failed to set texture parameters";
                        return false;
                    }

                    if (static_cast<GLsizei>(uploadData.size.v[0]) != width ||
                        static_cast<GLsizei>(uploadData.size.v[1]) != height)
                    {
                        width = static_cast<GLsizei>(uploadData.size.v[0]);
                        height = static_cast<GLsizei>(uploadData.size.v[1]);

                        for (size_t level = 0; level < uploadData.levels.size(); ++level)
                        {
                            glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), GL_RGBA,
                                         static_cast<GLsizei>(uploadData.levels[level].size.v[0]),
                                         static_cast<GLsizei>(uploadData.levels[level].size.v[1]), 0,
                                         GL_RGBA, GL_UNSIGNED_BYTE, uploadData.levels[level].data.data());
                        }
                    }
                    else
                    {
                        for (size_t level = 0; level < uploadData.levels.size(); ++level)
                        {
                            glTexSubImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), 0, 0,
                                            static_cast<GLsizei>(uploadData.levels[level].size.v[0]),
                                            static_cast<GLsizei>(uploadData.levels[level].size.v[1]),
                                            GL_RGBA, GL_UNSIGNED_BYTE, uploadData.levels[level].data.data());

                            if (RendererOGL::checkOpenGLError())
                            {
                                Log(Log::Level::ERR) << "Failed to upload texture data";
                                return false;
                            }
                        }
                    }
                }

                uploadData.dirty = false;
            }

            return true;
        }
    } // namespace graphics
} // namespace ouzel
<commit_msg>Fix OpenGL filtering no mip-maps<commit_after>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "TextureOGL.h"
#include "core/Engine.h"
#include "RendererOGL.h"
#include "graphics/Image.h"
#include "utils/Log.h"

namespace ouzel
{
    namespace graphics
    {
        TextureOGL::TextureOGL()
        {
        }

        TextureOGL::~TextureOGL()
        {
            if (textureId)
            {
                RendererOGL::deleteResource(textureId, RendererOGL::ResourceType::Texture);
            }
        }

        void TextureOGL::free()
        {
            Texture::free();

            if (textureId)
            {
                RendererOGL::deleteResource(textureId, RendererOGL::ResourceType::Texture);
                textureId = 0;
            }

            width = 0;
            height = 0;
        }

        bool TextureOGL::upload()
        {
            if (uploadData.dirty)
            {
                if (!textureId)
                {
                    glGenTextures(1, &textureId);

                    if (RendererOGL::checkOpenGLError())
                    {
                        Log(Log::Level::ERR) << "Failed to create texture";
                        return false;
                    }
                }

                if (!uploadData.levels.empty())
                {
                    RendererOGL::bindTexture(textureId, 0);

                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

                    RendererOGL* rendererOGL = static_cast<RendererOGL*>(sharedEngine->getRenderer());

                    if (uploadData.mipmaps) // has mip-maps
                    {
                        switch (rendererOGL->getTextureFilter())
                        {
                            case TextureFilter::NONE:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                                break;
                            case TextureFilter::LINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                                break;
                            case TextureFilter::BILINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                                break;
                            case TextureFilter::TRILINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                                break;
                        }
                    }
                    else
                    {
                        switch (rendererOGL->getTextureFilter())
                        {
                            case TextureFilter::NONE:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                                break;
                            case TextureFilter::LINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                                break;
                            case TextureFilter::BILINEAR:
                            case TextureFilter::TRILINEAR:
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                                break;
                        }
                    }

                    if (RendererOGL::checkOpenGLError())
                    {
                        Log(Log::Level::ERR) << "Failed to set texture parameters";
                        return false;
                    }

                    if (static_cast<GLsizei>(uploadData.size.v[0]) != width ||
                        static_cast<GLsizei>(uploadData.size.v[1]) != height)
                    {
                        width = static_cast<GLsizei>(uploadData.size.v[0]);
                        height = static_cast<GLsizei>(uploadData.size.v[1]);

                        for (size_t level = 0; level < uploadData.levels.size(); ++level)
                        {
                            glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), GL_RGBA,
                                         static_cast<GLsizei>(uploadData.levels[level].size.v[0]),
                                         static_cast<GLsizei>(uploadData.levels[level].size.v[1]), 0,
                                         GL_RGBA, GL_UNSIGNED_BYTE, uploadData.levels[level].data.data());
                        }
                    }
                    else
                    {
                        for (size_t level = 0; level < uploadData.levels.size(); ++level)
                        {
                            glTexSubImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), 0, 0,
                                            static_cast<GLsizei>(uploadData.levels[level].size.v[0]),
                                            static_cast<GLsizei>(uploadData.levels[level].size.v[1]),
                                            GL_RGBA, GL_UNSIGNED_BYTE, uploadData.levels[level].data.data());

                            if (RendererOGL::checkOpenGLError())
                            {
                                Log(Log::Level::ERR) << "Failed to upload texture data";
                                return false;
                            }
                        }
                    }
                }

                uploadData.dirty = false;
            }

            return true;
        }
    } // namespace graphics
} // namespace ouzel
<|endoftext|>


<commit_before>//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// MCSection
//===----------------------------------------------------------------------===//

MCSection::~MCSection() {
}

//===----------------------------------------------------------------------===//
// MCSectionELF
//===----------------------------------------------------------------------===//

MCSectionELF *MCSectionELF::
Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
  return new (Ctx) MCSectionELF(Name, IsDirective, K, Ctx);
}

MCSectionELF::MCSectionELF(const StringRef &name, bool isDirective,
                           SectionKind K, MCContext &Ctx)
  : MCSection(K), Name(name), IsDirective(isDirective) {
  Ctx.SetSection(Name, this);
}

void MCSectionELF::PrintSwitchToSection(const TargetAsmInfo &TAI,
                                        raw_ostream &OS) const {
  if (isDirective()) {
    OS << getName() << '\n';
    return;
  }

  OS << "\t.section\t" << getName();

  // Handle the weird solaris syntax if desired.
  if (TAI.usesSunStyleELFSectionSwitchSyntax() &&
      !getKind().isMergeableConst() && !getKind().isMergeableCString()) {
    if (!getKind().isMetadata())
      OS << ",#alloc";
    if (getKind().isText())
      OS << ",#execinstr";
    if (getKind().isWriteable())
      OS << ",#write";
    if (getKind().isThreadLocal())
      OS << ",#tls";
  } else {
    OS << ",\"";

    if (!getKind().isMetadata())
      OS << 'a';
    if (getKind().isText())
      OS << 'x';
    if (getKind().isWriteable())
      OS << 'w';
    if (getKind().isMergeable1ByteCString() ||
        getKind().isMergeable2ByteCString() ||
        getKind().isMergeable4ByteCString() ||
        getKind().isMergeableConst4() ||
        getKind().isMergeableConst8() ||
        getKind().isMergeableConst16())
      OS << 'M';
    if (getKind().isMergeable1ByteCString() ||
        getKind().isMergeable2ByteCString() ||
        getKind().isMergeable4ByteCString())
      OS << 'S';
    if (getKind().isThreadLocal())
      OS << 'T';

    OS << "\",";

    // If comment string is '@', e.g. as on ARM - use '%' instead
    if (TAI.getCommentString()[0] == '@')
      OS << '%';
    else
      OS << '@';

    if (getKind().isBSS() || getKind().isThreadBSS())
      OS << "nobits";
    else
      OS << "progbits";

    if (getKind().isMergeable1ByteCString()) {
      OS << ",1";
    } else if (getKind().isMergeable2ByteCString()) {
      OS << ",2";
    } else if (getKind().isMergeable4ByteCString()) {
      OS << ",4";
    } else if (getKind().isMergeableConst4()) {
      OS << ",4";
    } else if (getKind().isMergeableConst8()) {
      OS << ",8";
    } else if (getKind().isMergeableConst16()) {
      OS << ",16";
    }
  }
}

//===----------------------------------------------------------------------===//
// MCSectionMachO
//===----------------------------------------------------------------------===//

MCSectionMachO *MCSectionMachO::
Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
  return new (Ctx) MCSectionMachO(Name, IsDirective, K, Ctx);
}

MCSectionMachO::MCSectionMachO(const StringRef &name, bool isDirective,
                               SectionKind K, MCContext &Ctx)
  : MCSection(K), Name(name), IsDirective(isDirective) {
  Ctx.SetSection(Name, this);
}

void MCSectionMachO::PrintSwitchToSection(const TargetAsmInfo &TAI,
                                          raw_ostream &OS) const {
  if (!isDirective())
    OS << "\t.section\t" << getName() << '\n';
  else
    OS << getName() << '\n';
}

//===----------------------------------------------------------------------===//
// MCSectionCOFF
//===----------------------------------------------------------------------===//

MCSectionCOFF *MCSectionCOFF::
Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
  return new (Ctx) MCSectionCOFF(Name, IsDirective, K, Ctx);
}

MCSectionCOFF::MCSectionCOFF(const StringRef &name, bool isDirective,
                             SectionKind K, MCContext &Ctx)
  : MCSection(K), Name(name), IsDirective(isDirective) {
  Ctx.SetSection(Name, this);
}

void MCSectionCOFF::PrintSwitchToSection(const TargetAsmInfo &TAI,
                                         raw_ostream &OS) const {

  if (isDirective()) {
    OS << getName() << '\n';
    return;
  }
  OS << "\t.section\t" << getName() << ",\"";
  if (getKind().isText())
    OS << 'x';
  if (getKind().isWriteable())
    OS << 'w';
  OS << "\"\n";
}
<commit_msg>always end a section with \n on elf.<commit_after>//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// MCSection
//===----------------------------------------------------------------------===//

MCSection::~MCSection() {
}

//===----------------------------------------------------------------------===//
// MCSectionELF
//===----------------------------------------------------------------------===//

MCSectionELF *MCSectionELF::
Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
  return new (Ctx) MCSectionELF(Name, IsDirective, K, Ctx);
}

MCSectionELF::MCSectionELF(const StringRef &name, bool isDirective,
                           SectionKind K, MCContext &Ctx)
  : MCSection(K), Name(name), IsDirective(isDirective) {
  Ctx.SetSection(Name, this);
}

void MCSectionELF::PrintSwitchToSection(const TargetAsmInfo &TAI,
                                        raw_ostream &OS) const {
  if (isDirective()) {
    OS << getName() << '\n';
    return;
  }

  OS << "\t.section\t" << getName();

  // Handle the weird solaris syntax if desired.
  if (TAI.usesSunStyleELFSectionSwitchSyntax() &&
      !getKind().isMergeableConst() && !getKind().isMergeableCString()) {
    if (!getKind().isMetadata())
      OS << ",#alloc";
    if (getKind().isText())
      OS << ",#execinstr";
    if (getKind().isWriteable())
      OS << ",#write";
    if (getKind().isThreadLocal())
      OS << ",#tls";
  } else {
    OS << ",\"";

    if (!getKind().isMetadata())
      OS << 'a';
    if (getKind().isText())
      OS << 'x';
    if (getKind().isWriteable())
      OS << 'w';
    if (getKind().isMergeable1ByteCString() ||
        getKind().isMergeable2ByteCString() ||
        getKind().isMergeable4ByteCString() ||
        getKind().isMergeableConst4() ||
        getKind().isMergeableConst8() ||
        getKind().isMergeableConst16())
      OS << 'M';
    if (getKind().isMergeable1ByteCString() ||
        getKind().isMergeable2ByteCString() ||
        getKind().isMergeable4ByteCString())
      OS << 'S';
    if (getKind().isThreadLocal())
      OS << 'T';

    OS << "\",";

    // If comment string is '@', e.g. as on ARM - use '%' instead
    if (TAI.getCommentString()[0] == '@')
      OS << '%';
    else
      OS << '@';

    if (getKind().isBSS() || getKind().isThreadBSS())
      OS << "nobits";
    else
      OS << "progbits";

    if (getKind().isMergeable1ByteCString()) {
      OS << ",1";
    } else if (getKind().isMergeable2ByteCString()) {
      OS << ",2";
    } else if (getKind().isMergeable4ByteCString()) {
      OS << ",4";
    } else if (getKind().isMergeableConst4()) {
      OS << ",4";
    } else if (getKind().isMergeableConst8()) {
      OS << ",8";
    } else if (getKind().isMergeableConst16()) {
      OS << ",16";
    }
  }

  OS << '\n';
}

//===----------------------------------------------------------------------===//
// MCSectionMachO
//===----------------------------------------------------------------------===//

MCSectionMachO *MCSectionMachO::
Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
  return new (Ctx) MCSectionMachO(Name, IsDirective, K, Ctx);
}

MCSectionMachO::MCSectionMachO(const StringRef &name, bool isDirective,
                               SectionKind K, MCContext &Ctx)
  : MCSection(K), Name(name), IsDirective(isDirective) {
  Ctx.SetSection(Name, this);
}

void MCSectionMachO::PrintSwitchToSection(const TargetAsmInfo &TAI,
                                          raw_ostream &OS) const {
  if (!isDirective())
    OS << "\t.section\t" << getName() << '\n';
  else
    OS << getName() << '\n';
}

//===----------------------------------------------------------------------===//
// MCSectionCOFF
//===----------------------------------------------------------------------===//

MCSectionCOFF *MCSectionCOFF::
Create(const StringRef &Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
  return new (Ctx) MCSectionCOFF(Name, IsDirective, K, Ctx);
}

MCSectionCOFF::MCSectionCOFF(const StringRef &name, bool isDirective,
                             SectionKind K, MCContext &Ctx)
  : MCSection(K), Name(name), IsDirective(isDirective) {
  Ctx.SetSection(Name, this);
}

void MCSectionCOFF::PrintSwitchToSection(const TargetAsmInfo &TAI,
                                         raw_ostream &OS) const {

  if (isDirective()) {
    OS << getName() << '\n';
    return;
  }
  OS << "\t.section\t" << getName() << ",\"";
  if (getKind().isText())
    OS << 'x';
  if (getKind().isWriteable())
    OS << 'w';
  OS << "\"\n";
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////

#include "Rest/Version.h"

#ifdef _WIN32
#include "Basics/win-utils.h"
#endif

#include <openssl/ssl.h>
#include <sstream>

#include <velocypack/Builder.h>
#include <velocypack/Version.h>
#include <velocypack/velocypack-aliases.h>

#include "Basics/StringUtils.h"
#include "Basics/Utf8Helper.h"
#include "Basics/build-date.h"
#include "Basics/build-repository.h"
#include "Basics/conversions.h"

#include <rocksdb/version.h>

using namespace arangodb::rest;

std::map<std::string, std::string> Version::Values;

////////////////////////////////////////////////////////////////////////////////
/// @brief parse a version string into major, minor
/// returns -1, -1 when the version string has an invalid format
/// returns major, -1 when only the major version can be determined
////////////////////////////////////////////////////////////////////////////////

std::pair<int, int> Version::parseVersionString(std::string const& str) {
  std::pair<int, int> result{ -1, -1 };

  if (!str.empty()) {
    char const* p = str.c_str();
    char const* q = p;
    while (*q >= '0' && *q <= '9') {
      ++q;
    }
    if (p != q) {
      result.first = std::stoi(std::string(p, q - p));
      result.second = 0;

      if (*q == '.') {
        ++q;
      }
      p = q;
      while (*q >= '0' && *q <= '9') {
        ++q;
      }
      if (p != q) {
        result.second = std::stoi(std::string(p, q - p));
      }
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief initialize
////////////////////////////////////////////////////////////////////////////////

void Version::initialize() {
  if (!Values.empty()) {
    return;
  }

  Values["architecture"] = (sizeof(void*) == 4 ? "32" : "64") + std::string("bit");
  Values["asm-crc32"] = (ENABLE_ASM_CRC32) ? "true" : "false";
  Values["boost-version"] = getBoostVersion();
  Values["build-date"] = getBuildDate();
  Values["compiler"] = getCompiler();
  Values["endianness"] = getEndianness();
  Values["fd-setsize"] = arangodb::basics::StringUtils::itoa(FD_SETSIZE);
  Values["icu-version"] = getICUVersion();
  Values["libev-version"] = getLibevVersion();
  Values["openssl-version"] = getOpenSSLVersion();
  Values["server-version"] = getServerVersion();
  Values["sizeof int"] = arangodb::basics::StringUtils::itoa(sizeof(int));
  Values["sizeof void*"] = arangodb::basics::StringUtils::itoa(sizeof(void*));
  Values["v8-version"] = getV8Version();
  Values["vpack-version"] = getVPackVersion();
  Values["zlib-version"] = getZLibVersion();

#if USE_ENTERPRISE
  Values["enterprise-version"] = ARANGODB_ENTERPRISE_VERSION;
#endif

#if HAVE_ARANGODB_BUILD_REPOSITORY
  Values["build-repository"] = getBuildRepository();
#endif

#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
  Values["assertions"] = "true";
#else
  Values["assertions"] = "false";
#endif

  Values["rocksdb-version"] = std::to_string(ROCKSDB_MAJOR) + "." + std::to_string(ROCKSDB_MINOR) + "." + std::to_string(ROCKSDB_PATCH);

#ifdef __cplusplus
  Values["cplusplus"] = std::to_string(__cplusplus);
#else
  Values["cplusplus"] = "unknown";
#endif

#ifdef __SANITIZE_ADDRESS__
  Values["asan"] = "true";
#else
  Values["asan"] = "false";
#endif

#if defined(__SSE4_2__) && !defined(NO_SSE42)
  Values["sse42"] = "true";
#else
  Values["sse42"] = "false";
#endif

#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
  Values["maintainer-mode"] = "true";
#else
  Values["maintainer-mode"] = "false";
#endif

#ifdef ARANGODB_HAVE_TCMALLOC
  Values["tcmalloc"] = "true";
#else
  Values["tcmalloc"] = "false";
#endif

#ifdef ARANGODB_HAVE_JEMALLOC
  Values["jemalloc"] = "true";
#else
  Values["jemalloc"] = "false";
#endif

#ifdef TRI_HAVE_POLL_H
  Values["fd-client-event-handler"] = "poll";
#else
  Values["fd-client-event-handler"] = "select";
#endif

  for (auto& it : Values) {
    arangodb::basics::StringUtils::trimInPlace(it.second);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get numeric server version
////////////////////////////////////////////////////////////////////////////////

int32_t Version::getNumericServerVersion() {
  char const* apiVersion = ARANGODB_VERSION;
  char const* p = apiVersion;

  // read major version
  while (*p >= '0' && *p <= '9') {
    ++p;
  }

  TRI_ASSERT(*p == '.');
  int32_t major = TRI_Int32String2(apiVersion, (p - apiVersion));

  apiVersion = ++p;

  // read minor version
  while (*p >= '0' && *p <= '9') {
    ++p;
  }

  TRI_ASSERT((*p == '.' || *p == '-' || *p == '\0') && p != apiVersion);
  int32_t minor = TRI_Int32String2(apiVersion, (p - apiVersion));

  return (int32_t)(minor * 100L + major * 10000L);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get server version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getServerVersion() { return std::string(ARANGODB_VERSION); }

////////////////////////////////////////////////////////////////////////////////
/// @brief get BOOST version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getBoostVersion() {
#ifdef ARANGODB_BOOST_VERSION
  return std::string(ARANGODB_BOOST_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get V8 version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getV8Version() {
#ifdef ARANGODB_V8_VERSION
  return std::string(ARANGODB_V8_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get OpenSSL version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getOpenSSLVersion() {
#ifdef OPENSSL_VERSION_TEXT
  return std::string(OPENSSL_VERSION_TEXT);
#elif defined(ARANGODB_OPENSSL_VERSION)
  return std::string(ARANGODB_OPENSSL_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get libev version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getLibevVersion() {
#ifdef ARANGODB_LIBEV_VERSION
  return std::string(ARANGODB_LIBEV_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get vpack version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getVPackVersion() {
  return arangodb::velocypack::Version::BuildVersion.toString();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get zlib version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getZLibVersion() {
#ifdef ARANGODB_ZLIB_VERSION
  return std::string(ARANGODB_ZLIB_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get ICU version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getICUVersion() {
  UVersionInfo icuVersion;
  char icuVersionString[U_MAX_VERSION_STRING_LENGTH];
  u_getVersion(icuVersion);
  u_versionToString(icuVersion, icuVersionString);

  return icuVersionString;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get compiler
////////////////////////////////////////////////////////////////////////////////

std::string Version::getCompiler() {
#if defined(__clang__)
  return "clang [" + std::string(__VERSION__) + "]";
#elif defined(__GNUC__) || defined(__GNUG__)
  return "gcc [" + std::string(__VERSION__) + "]";
#elif defined(_MSC_VER)
  return "msvc [" + std::to_string(_MSC_VER) + "]";
#endif
  return "unknown";
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get endianness
////////////////////////////////////////////////////////////////////////////////

std::string Version::getEndianness() {
  uint64_t value = 0x12345678abcdef99;
  static_assert(sizeof(value) == 8, "unexpected uint64_t size");

  unsigned char const* p = reinterpret_cast<unsigned char const*>(&value);
  if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78 && p[4] == 0xab && p[5] == 0xcd && p[6] == 0xef && p[7] == 0x99) {
    return "big";
  }

  if (p[0] == 0x99 && p[1] == 0xef && p[2] == 0xcd && p[3] == 0xab && p[4] == 0x78 && p[5] == 0x56 && p[6] == 0x34 && p[7] == 0x12) {
    return "little";
  }
  return "unknown";
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get build date
////////////////////////////////////////////////////////////////////////////////

std::string Version::getBuildDate() {
// the OpenSuSE build system does not like it, if __DATE__ is used
#ifdef ARANGODB_BUILD_DATE
  return std::string(ARANGODB_BUILD_DATE);
#else
  return std::string(__DATE__).append(" ").append(__TIME__);
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get build repository
////////////////////////////////////////////////////////////////////////////////

std::string Version::getBuildRepository() {
#ifdef HAVE_ARANGODB_BUILD_REPOSITORY
  return std::string(ARANGODB_BUILD_REPOSITORY);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return a server version string
////////////////////////////////////////////////////////////////////////////////

std::string Version::getVerboseVersionString() {
  std::ostringstream version;

  version << "ArangoDB " << ARANGODB_VERSION_FULL << " "
          << (sizeof(void*) == 4 ? "32" : "64") << "bit"
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
          << " maintainer mode"
#endif
#ifdef __SANITIZE_ADDRESS__
          << " with ASAN"
#endif
          << ", using "
#ifdef TRI_HAVE_TCMALLOC
          << "tcmalloc, "
#endif
#ifdef TRI_HAVE_JEMALLOC
          << "jemalloc, "
#endif
          << "VPack " << getVPackVersion() << ", "
          << "ICU " << getICUVersion() << ", "
          << "V8 " << getV8Version() << ", " << getOpenSSLVersion();

  return version.str();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get detailed version information as a (multi-line) string
////////////////////////////////////////////////////////////////////////////////

std::string Version::getDetailed() {
  std::string result;

  for (auto& it : Values) {
    std::string const& value = it.second;

    if (!value.empty()) {
      result.append(it.first);
      result.append(": ");
      result.append(it.second);
#ifdef _WIN32
      result += "\r\n";
#else
      result += "\n";
#endif
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief VelocyPack all data
////////////////////////////////////////////////////////////////////////////////

void Version::getVPack(VPackBuilder& dst) {
  TRI_ASSERT(!dst.isClosed());

  for (auto const& it : Values) {
    std::string const& value = it.second;

    if (!value.empty()) {
      dst.add(it.first, VPackValue(value));
    }
  }
}

<commit_msg>report value of ARANGODB_USE_FAILURE_TESTS<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////

#include "Rest/Version.h"

#ifdef _WIN32
#include "Basics/win-utils.h"
#endif

#include <openssl/ssl.h>
#include <sstream>

#include <velocypack/Builder.h>
#include <velocypack/Version.h>
#include <velocypack/velocypack-aliases.h>

#include "Basics/StringUtils.h"
#include "Basics/Utf8Helper.h"
#include "Basics/build-date.h"
#include "Basics/build-repository.h"
#include "Basics/conversions.h"

#include <rocksdb/version.h>

using namespace arangodb::rest;

std::map<std::string, std::string> Version::Values;

////////////////////////////////////////////////////////////////////////////////
/// @brief parse a version string into major, minor
/// returns -1, -1 when the version string has an invalid format
/// returns major, -1 when only the major version can be determined
////////////////////////////////////////////////////////////////////////////////

std::pair<int, int> Version::parseVersionString(std::string const& str) {
  std::pair<int, int> result{ -1, -1 };

  if (!str.empty()) {
    char const* p = str.c_str();
    char const* q = p;
    while (*q >= '0' && *q <= '9') {
      ++q;
    }
    if (p != q) {
      result.first = std::stoi(std::string(p, q - p));
      result.second = 0;

      if (*q == '.') {
        ++q;
      }
      p = q;
      while (*q >= '0' && *q <= '9') {
        ++q;
      }
      if (p != q) {
        result.second = std::stoi(std::string(p, q - p));
      }
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief initialize
////////////////////////////////////////////////////////////////////////////////

void Version::initialize() {
  if (!Values.empty()) {
    return;
  }

  Values["architecture"] = (sizeof(void*) == 4 ? "32" : "64") + std::string("bit");
  Values["asm-crc32"] = (ENABLE_ASM_CRC32) ? "true" : "false";
  Values["boost-version"] = getBoostVersion();
  Values["build-date"] = getBuildDate();
  Values["compiler"] = getCompiler();
  Values["endianness"] = getEndianness();
  Values["fd-setsize"] = arangodb::basics::StringUtils::itoa(FD_SETSIZE);
  Values["icu-version"] = getICUVersion();
  Values["libev-version"] = getLibevVersion();
  Values["openssl-version"] = getOpenSSLVersion();
  Values["server-version"] = getServerVersion();
  Values["sizeof int"] = arangodb::basics::StringUtils::itoa(sizeof(int));
  Values["sizeof void*"] = arangodb::basics::StringUtils::itoa(sizeof(void*));
  Values["v8-version"] = getV8Version();
  Values["vpack-version"] = getVPackVersion();
  Values["zlib-version"] = getZLibVersion();

#if USE_ENTERPRISE
  Values["enterprise-version"] = ARANGODB_ENTERPRISE_VERSION;
#endif

#if HAVE_ARANGODB_BUILD_REPOSITORY
  Values["build-repository"] = getBuildRepository();
#endif

#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
  Values["assertions"] = "true";
#else
  Values["assertions"] = "false";
#endif

  Values["rocksdb-version"] = std::to_string(ROCKSDB_MAJOR) + "." + std::to_string(ROCKSDB_MINOR) + "." + std::to_string(ROCKSDB_PATCH);

#ifdef __cplusplus
  Values["cplusplus"] = std::to_string(__cplusplus);
#else
  Values["cplusplus"] = "unknown";
#endif

#ifdef __SANITIZE_ADDRESS__
  Values["asan"] = "true";
#else
  Values["asan"] = "false";
#endif

#if defined(__SSE4_2__) && !defined(NO_SSE42)
  Values["sse42"] = "true";
#else
  Values["sse42"] = "false";
#endif

#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
  Values["maintainer-mode"] = "true";
#else
  Values["maintainer-mode"] = "false";
#endif

#ifdef ARANGODB_ENABLE_FAILURE_TESTS
  Values["failure-tests"] = "true";
#else
  Values["failure-tests"] = "false";
#endif

#ifdef ARANGODB_HAVE_TCMALLOC
  Values["tcmalloc"] = "true";
#else
  Values["tcmalloc"] = "false";
#endif

#ifdef ARANGODB_HAVE_JEMALLOC
  Values["jemalloc"] = "true";
#else
  Values["jemalloc"] = "false";
#endif

#ifdef TRI_HAVE_POLL_H
  Values["fd-client-event-handler"] = "poll";
#else
  Values["fd-client-event-handler"] = "select";
#endif

  for (auto& it : Values) {
    arangodb::basics::StringUtils::trimInPlace(it.second);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get numeric server version
////////////////////////////////////////////////////////////////////////////////

int32_t Version::getNumericServerVersion() {
  char const* apiVersion = ARANGODB_VERSION;
  char const* p = apiVersion;

  // read major version
  while (*p >= '0' && *p <= '9') {
    ++p;
  }

  TRI_ASSERT(*p == '.');
  int32_t major = TRI_Int32String2(apiVersion, (p - apiVersion));

  apiVersion = ++p;

  // read minor version
  while (*p >= '0' && *p <= '9') {
    ++p;
  }

  TRI_ASSERT((*p == '.' || *p == '-' || *p == '\0') && p != apiVersion);
  int32_t minor = TRI_Int32String2(apiVersion, (p - apiVersion));

  return (int32_t)(minor * 100L + major * 10000L);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get server version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getServerVersion() { return std::string(ARANGODB_VERSION); }

////////////////////////////////////////////////////////////////////////////////
/// @brief get BOOST version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getBoostVersion() {
#ifdef ARANGODB_BOOST_VERSION
  return std::string(ARANGODB_BOOST_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get V8 version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getV8Version() {
#ifdef ARANGODB_V8_VERSION
  return std::string(ARANGODB_V8_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get OpenSSL version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getOpenSSLVersion() {
#ifdef OPENSSL_VERSION_TEXT
  return std::string(OPENSSL_VERSION_TEXT);
#elif defined(ARANGODB_OPENSSL_VERSION)
  return std::string(ARANGODB_OPENSSL_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get libev version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getLibevVersion() {
#ifdef ARANGODB_LIBEV_VERSION
  return std::string(ARANGODB_LIBEV_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get vpack version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getVPackVersion() {
  return arangodb::velocypack::Version::BuildVersion.toString();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get zlib version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getZLibVersion() {
#ifdef ARANGODB_ZLIB_VERSION
  return std::string(ARANGODB_ZLIB_VERSION);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get ICU version
////////////////////////////////////////////////////////////////////////////////

std::string Version::getICUVersion() {
  UVersionInfo icuVersion;
  char icuVersionString[U_MAX_VERSION_STRING_LENGTH];
  u_getVersion(icuVersion);
  u_versionToString(icuVersion, icuVersionString);

  return icuVersionString;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get compiler
////////////////////////////////////////////////////////////////////////////////

std::string Version::getCompiler() {
#if defined(__clang__)
  return "clang [" + std::string(__VERSION__) + "]";
#elif defined(__GNUC__) || defined(__GNUG__)
  return "gcc [" + std::string(__VERSION__) + "]";
#elif defined(_MSC_VER)
  return "msvc [" + std::to_string(_MSC_VER) + "]";
#endif
  return "unknown";
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get endianness
////////////////////////////////////////////////////////////////////////////////

std::string Version::getEndianness() {
  uint64_t value = 0x12345678abcdef99;
  static_assert(sizeof(value) == 8, "unexpected uint64_t size");

  unsigned char const* p = reinterpret_cast<unsigned char const*>(&value);
  if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78 && p[4] == 0xab && p[5] == 0xcd && p[6] == 0xef && p[7] == 0x99) {
    return "big";
  }

  if (p[0] == 0x99 && p[1] == 0xef && p[2] == 0xcd && p[3] == 0xab && p[4] == 0x78 && p[5] == 0x56 && p[6] == 0x34 && p[7] == 0x12) {
    return "little";
  }
  return "unknown";
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get build date
////////////////////////////////////////////////////////////////////////////////

std::string Version::getBuildDate() {
// the OpenSuSE build system does not like it, if __DATE__ is used
#ifdef ARANGODB_BUILD_DATE
  return std::string(ARANGODB_BUILD_DATE);
#else
  return std::string(__DATE__).append(" ").append(__TIME__);
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get build repository
////////////////////////////////////////////////////////////////////////////////

std::string Version::getBuildRepository() {
#ifdef HAVE_ARANGODB_BUILD_REPOSITORY
  return std::string(ARANGODB_BUILD_REPOSITORY);
#else
  return std::string("");
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return a server version string
////////////////////////////////////////////////////////////////////////////////

std::string Version::getVerboseVersionString() {
  std::ostringstream version;

  version << "ArangoDB " << ARANGODB_VERSION_FULL << " "
          << (sizeof(void*) == 4 ? "32" : "64") << "bit"
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
          << " maintainer mode"
#endif
#ifdef __SANITIZE_ADDRESS__
          << " with ASAN"
#endif
          << ", using "
#ifdef TRI_HAVE_TCMALLOC
          << "tcmalloc, "
#endif
#ifdef TRI_HAVE_JEMALLOC
          << "jemalloc, "
#endif
          << "VPack " << getVPackVersion() << ", "
          << "ICU " << getICUVersion() << ", "
          << "V8 " << getV8Version() << ", " << getOpenSSLVersion();

  return version.str();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get detailed version information as a (multi-line) string
////////////////////////////////////////////////////////////////////////////////

std::string Version::getDetailed() {
  std::string result;

  for (auto& it : Values) {
    std::string const& value = it.second;

    if (!value.empty()) {
      result.append(it.first);
      result.append(": ");
      result.append(it.second);
#ifdef _WIN32
      result += "\r\n";
#else
      result += "\n";
#endif
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief VelocyPack all data
////////////////////////////////////////////////////////////////////////////////

void Version::getVPack(VPackBuilder& dst) {
  TRI_ASSERT(!dst.isClosed());

  for (auto const& it : Values) {
    std::string const& value = it.second;

    if (!value.empty()) {
      dst.add(it.first, VPackValue(value));
    }
  }
}

<|endoftext|>