<commit_before>//
//  MapData
//  InternetMap
//

#include "MapData.hpp"
#include "Node.hpp"
#include "DisplayLines.hpp"
#include "Connection.hpp"
#include "IndexBox.hpp"
#include "MapDisplay.hpp"
#include <sstream>
#include <stdlib.h>
#include <fstream>
#include <assert.h>

// TODO: figure out how to do this right
#ifdef ANDROID
#include "jsoncpp/json.h"
#else
#include "json.h"
#endif

static const char *ASNS_AT_TOP[] = {"13768", "23498", "3", "15169", "714", "32934", "7847"}; //Peer1, Cogeco, MIT, google, apple, facebook, NASA
static const int NUM_ASNS_AT_TOP = 7;

NodePointer MapData::nodeAtIndex(unsigned int index) {
    return nodes[index];
}

void split( std::vector<std::string> & theStringVector,  /* Altered/returned value */
      const  std::string  & theString,
      const  std::string  & theDelimiter)
{
    size_t  start = 0, end = 0;

    while ( end != std::string::npos)
    {
        end = theString.find( theDelimiter, start);

        // If at end, use length=maxLength.  Else use length=end-start.
        theStringVector.push_back( theString.substr( start,
                                                    (end == std::string::npos) ? std::string::npos : end - start));

        // If at end, use start=maxSize.  Else use start=end+delimiter.
        start = (   ( end > (std::string::npos - theDelimiter.size()) )
                 ?  std::string::npos  :  end + theDelimiter.size());
    }
}

static const int MAX_TOKEN_SIZE = 256;

const char* nextToken(const char* source, char* token, bool* lineEnd, char separator = ' ') {
    *lineEnd = false;

    while ((*source != separator) && (*source != '\n') && (*source != 0)) {
        *token++ = *source++;
    }

    *lineEnd |= *source == '\n';

    *token = 0;

    if(*source != 0) {
        while ((*source == separator) || (*source == '\n')) {
            source++;
            *lineEnd |= *source == '\n';
        }
    }

    return source;
}

void MapData::resetToDefault() {
    for(int i = 0; i < nodes.size(); i++) {
        Node* node = nodes[i].get();

        node->timelineActive = node->activeDefault;
        if(node->activeDefault) {
            node->positionX = node->defaultPositionX;
            node->positionY = node->defaultPositionY;
            node->importance = node->defaultImportance;
        }
    }

    connections = defaultConnections;

    visualization->activate(nodes);

    createNodeBoxes();
}

void MapData::loadFromString(const std::string& text) {
    // Connections an boxes are always fully regenerated
    connections.erase(connections.begin(), connections.end());

    // Mark all nodes as inactive (they will be reactivated if they are in the current data set)
    for(int i = 0; i < nodes.size(); i++) {
        nodes[i]->timelineActive = false;
    }

    const char* sourceText = text.c_str();
    char token[MAX_TOKEN_SIZE];
    bool lineEnd;
    int numNodes, numConnections;

    bool firstLoad = nodes.size() == 0;

    // Grab header data (node and connection counts)
    sourceText = nextToken(sourceText, token, &lineEnd);
    numNodes = atof(token);

    sourceText = nextToken(sourceText, token, &lineEnd);
    numConnections = atof(token);

    if (nodes.size() == 0) {
        LOG("initializing nodes vector (total %d)", numNodes);
        nodes.reserve(numNodes);
        nodes.resize(NUM_ASNS_AT_TOP);
        //LOG("nodes.size: %ld", nodes.size());
    }

    int missingNodes = 0;
    for (int i = 0; i < numNodes; i++) {
        // Grab asn
        sourceText = nextToken(sourceText, token, &lineEnd);

        // check for matching existing node
        NodePointer node = nodesByAsn[token];

        if(node) {
            // already thre, just mark as active
            node->timelineActive = true;
        }
        else {
            // Not there, create
            missingNodes++;

            node = NodePointer(new Node());
            node->asn = token;
            node->type = AS_UNKNOWN;
            node->timelineActive = true;

            //is it a special node?
            bool needInsert = false;
            for (int i=0; i<NUM_ASNS_AT_TOP; i++) {
                if (strcmp(token, ASNS_AT_TOP[i]) == 0) {
                    node->index = i;
                    needInsert = true;
                    //LOG("found special at index %d", node->index);
                    break;
                }
            }

            if (needInsert) {
                nodes[node->index] = node;
            } else {
                //regular nodes can just be appended.
                node->index = nodes.size();
                nodes.push_back(node);
            }
            nodesByAsn[node->asn] = node;
        }

        // Refill data that is unique to a particualar timeline position
        sourceText = nextToken(sourceText, token, &lineEnd);
        if(node) {
            node->importance = atof(token);
        }
        sourceText = nextToken(sourceText, token, &lineEnd);
        if(node) {
            node->positionX = atof(token);
        }
        sourceText = nextToken(sourceText, token, &lineEnd);
        if(node) {
            node->positionY = atof(token);
        }

        if(node && firstLoad) {
            node->defaultPositionX = node->positionX;
            node->defaultPositionY = node->positionY;
            node->defaultImportance = node->importance;
            node->activeDefault = true;
        }
    }

    // Load connections
    for (int i = 0; i < numConnections; i++) {
        ConnectionPointer connection(new Connection());

        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->first = nodesByAsn[token];
        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->second = nodesByAsn[token];

        if (connection->first && connection->second) {
            connection->first->connections.push_back(connection);
            connection->second->connections.push_back(connection);
            connections.push_back(connection);
        }
    }

    if(firstLoad) {
        defaultConnections = connections;
    }

    LOG("loaded data: %d nodes (this load), %d nodes (total), %d connections", missingNodes, (int)(nodes.size()), numConnections);

    visualization->activate(nodes);

    createNodeBoxes();
}

void MapData::loadFromAttrString(const std::string& json){
    std::map<std::string, int> asTypeDict;
    asTypeDict["abstained"] = AS_UNKNOWN;
    asTypeDict["t1"] = AS_T1;
    asTypeDict["t2"] = AS_T2;
    asTypeDict["comp"] = AS_COMP;
    asTypeDict["edu"] = AS_EDU;
    asTypeDict["ix"] = AS_IX;
    asTypeDict["nic"] = AS_NIC;

    std::map<int, std::string> friendlyTypeStrings;
    friendlyTypeStrings[(int)AS_UNKNOWN] = "Unknown Network Type";
    friendlyTypeStrings[(int)AS_T1] = "Large ISP";
    friendlyTypeStrings[(int)AS_T2] = "Small ISP";
    friendlyTypeStrings[(int)AS_COMP] = "Customer Network";
    friendlyTypeStrings[(int)AS_EDU] = "University";
    friendlyTypeStrings[(int)AS_IX] = "Internet Exchange Point";
    friendlyTypeStrings[(int)AS_NIC] = "Network Information Center";

    std::vector<std::string> lines;
    split(lines, json, "\n");

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

        std::string line = lines[i];
        std::vector<std::string> aDesc;
        split(aDesc, line, "\t");
        NodePointer node = nodesByAsn[aDesc[0]];

        if(node){

            node->type = asTypeDict[aDesc[7]];
            node->typeString = friendlyTypeStrings[node->type];
            node->rawTextDescription = aDesc[1];
        }
    }

//    NSLog(@"attr load : %.2fms", ([NSDate timeIntervalSinceReferenceDate] - start) * 1000.0f);

}

void MapData::loadASInfo(const std::string& json){

    Json::Value root;
    Json::Reader reader;
    bool success = reader.parse(json, root);
    if(success) {
        std::vector<std::string> members = root.getMemberNames();
        for (unsigned int i = 0; i < members.size(); i++) {
            NodePointer node = nodesByAsn[members[i]];
            if (node) {
                Json::Value as = root[members[i]];
//                node->name = as[1].asString();
//                node->rawTextDescription = as[5].asString();
//                node->dateRegistered = as[3].asString();
//                node->address = as[7].asString();
//                node->city = as[8].asString();
//                node->state = as[9].asString();
//                node->postalCode = as[10].asString();
//                node->country = as[11].asString();
//                node->hasLatLong = true;
//                node->latitude = as[12].asFloat()*2.0*3.14159/360.0;
//                node->longitude = as[13].asFloat()*2.0*3.14159/360.0;

                node->rawTextDescription = as[0].asString();
                node->hasLatLong = true;
                node->latitude = as[1].asFloat()*2.0*3.14159/360.0;
                node->longitude = as[2].asFloat()*2.0*3.14159/360.0;
            }
        }
    }
}

void MapData::loadUnified(const std::string& text) {
    const char* sourceText = text.c_str();

    char token[MAX_TOKEN_SIZE];
    bool lineEnd;
    int numNodes, numConnections;

    // Grab header data (node and connection counts)
    sourceText = nextToken(sourceText, token, &lineEnd);
    numNodes = atof(token);

    sourceText = nextToken(sourceText, token, &lineEnd);
    numConnections = atof(token);

    nodes.reserve(numNodes);

    for (int i = 0; i < numNodes; i++) {
        NodePointer node = NodePointer(new Node());
        node->timelineActive = true;
        node->activeDefault = true;

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->asn = token;

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        if(token[0] != '?') {
            node->rawTextDescription = token;
        }

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->type = atoi(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->hasLatLong = atoi(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->latitude = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->longitude = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->positionX = node->defaultPositionX = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->positionY = node->defaultPositionY = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->importance = node->defaultImportance = atof(token);

        assert(lineEnd);

        node->index = nodes.size();
        nodes.push_back(node);
        nodesByAsn[node->asn] = node;
    }

    // Load connections
    for (int i = 0; i < numConnections; i++) {
        ConnectionPointer connection(new Connection());

        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->first = nodesByAsn[token];
        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->second = nodesByAsn[token];

        if (connection->first && connection->second) {
            connection->first->connections.push_back(connection);
            connection->second->connections.push_back(connection);
            connections.push_back(connection);
        }
    }

    defaultConnections = connections;

    LOG("loaded default data: %d nodes, %d connections", (int)(nodes.size()), numConnections);

    visualization->activate(nodes);

    createNodeBoxes();
}

void MapData::createNodeBoxes() {
    boxesForNodes.erase(boxesForNodes.begin(), boxesForNodes.end());

    for (int k = 0; k < numberOfCellsZ; k++) {
        float z = IndexBoxMinZ + boxSizeZWithoutOverlap*k;
        for (int j = 0; j < numberOfCellsY; j++) {
            float y = IndexBoxMinY + boxSizeYWithoutOverlap*j;
            for(int i = 0; i < numberOfCellsX; i++) {
                float x = IndexBoxMinX + boxSizeXWithoutOverlap*i;
                IndexBoxPointer box = IndexBoxPointer(new IndexBox());
                box->setCenter(Point3(x+boxSizeXWithoutOverlap/2, y+boxSizeYWithoutOverlap/2, z+boxSizeZWithoutOverlap/2));
                box->setMinCorner(Point3(x, y, z));
                box->setMaxCorner(Point3(x+boxSizeXWithoutOverlap, y+boxSizeYWithoutOverlap, z+boxSizeZWithoutOverlap));
                boxesForNodes.push_back(box);
            }
        }
    }

    for (unsigned int i = 0; i < nodes.size(); i++) {
        NodePointer ptrNode = nodes.at(i);
        if(ptrNode->isActive()) {
            Point3 pos = visualization->nodePosition(ptrNode);
            IndexBoxPointer box = indexBoxForPoint(pos);
            box->indices.insert(i);
        }
    }
}

IndexBoxPointer MapData::indexBoxForPoint(const Point3& point) {

    int posX = (int)fabsf((point.getX() + fabsf(IndexBoxMinX))/boxSizeXWithoutOverlap);
    int posY = (int)fabsf((point.getY() + fabsf(IndexBoxMinY))/boxSizeYWithoutOverlap);
    int posZ = (int)fabsf((point.getZ() + fabsf(IndexBoxMinZ))/boxSizeZWithoutOverlap);
    int posInArray = posX + (fabsf(IndexBoxMinX) + fabsf(IndexBoxMaxX))/boxSizeXWithoutOverlap*posY + (fabsf(IndexBoxMinX) + fabsf(IndexBoxMaxX))/boxSizeXWithoutOverlap*(fabsf(IndexBoxMinY)+fabsf(IndexBoxMaxY))/boxSizeYWithoutOverlap*posZ;

    return boxesForNodes[posInArray];
}

void MapData::dumpUnified(void) {
    std::ofstream out("/Users/nigel/Downloads/unified.txt");
    out << nodes.size() << std::endl;
    out << connections.size() << std::endl;

    for(int i = 0; i < nodes.size(); i++) {
        std::string desc = nodes[i]->rawTextDescription;
        if(desc.length() == 0) {
            desc = "?";
        }

        out << nodes[i]->asn << "\t"
            << desc << "\t"
            << nodes[i]->type << "\t"
            << nodes[i]->hasLatLong << "\t"
            << nodes[i]->latitude << "\t"
            << nodes[i]->longitude << "\t"
            << nodes[i]->positionX << "\t"
            << nodes[i]->positionY << "\t"
            << nodes[i]->importance << "\t" << std::endl;
    }

    for(int i = 0; i < connections.size(); i++) {
        out << connections[i]->first->index << " " << connections[i]->second->index << std::endl;
    }
}
<commit_msg>Change "Customer Network" to "Organization Network"<commit_after>//
//  MapData
//  InternetMap
//

#include "MapData.hpp"
#include "Node.hpp"
#include "DisplayLines.hpp"
#include "Connection.hpp"
#include "IndexBox.hpp"
#include "MapDisplay.hpp"
#include <sstream>
#include <stdlib.h>
#include <fstream>
#include <assert.h>

// TODO: figure out how to do this right
#ifdef ANDROID
#include "jsoncpp/json.h"
#else
#include "json.h"
#endif

static const char *ASNS_AT_TOP[] = {"13768", "23498", "3", "15169", "714", "32934", "7847"}; //Peer1, Cogeco, MIT, google, apple, facebook, NASA
static const int NUM_ASNS_AT_TOP = 7;

NodePointer MapData::nodeAtIndex(unsigned int index) {
    return nodes[index];
}

void split( std::vector<std::string> & theStringVector,  /* Altered/returned value */
      const  std::string  & theString,
      const  std::string  & theDelimiter)
{
    size_t  start = 0, end = 0;

    while ( end != std::string::npos)
    {
        end = theString.find( theDelimiter, start);

        // If at end, use length=maxLength.  Else use length=end-start.
        theStringVector.push_back( theString.substr( start,
                                                    (end == std::string::npos) ? std::string::npos : end - start));

        // If at end, use start=maxSize.  Else use start=end+delimiter.
        start = (   ( end > (std::string::npos - theDelimiter.size()) )
                 ?  std::string::npos  :  end + theDelimiter.size());
    }
}

static const int MAX_TOKEN_SIZE = 256;

const char* nextToken(const char* source, char* token, bool* lineEnd, char separator = ' ') {
    *lineEnd = false;

    while ((*source != separator) && (*source != '\n') && (*source != 0)) {
        *token++ = *source++;
    }

    *lineEnd |= *source == '\n';

    *token = 0;

    if(*source != 0) {
        while ((*source == separator) || (*source == '\n')) {
            source++;
            *lineEnd |= *source == '\n';
        }
    }

    return source;
}

void MapData::resetToDefault() {
    for(int i = 0; i < nodes.size(); i++) {
        Node* node = nodes[i].get();

        node->timelineActive = node->activeDefault;
        if(node->activeDefault) {
            node->positionX = node->defaultPositionX;
            node->positionY = node->defaultPositionY;
            node->importance = node->defaultImportance;
        }
    }

    connections = defaultConnections;

    visualization->activate(nodes);

    createNodeBoxes();
}

void MapData::loadFromString(const std::string& text) {
    // Connections an boxes are always fully regenerated
    connections.erase(connections.begin(), connections.end());

    // Mark all nodes as inactive (they will be reactivated if they are in the current data set)
    for(int i = 0; i < nodes.size(); i++) {
        nodes[i]->timelineActive = false;
    }

    const char* sourceText = text.c_str();
    char token[MAX_TOKEN_SIZE];
    bool lineEnd;
    int numNodes, numConnections;

    bool firstLoad = nodes.size() == 0;

    // Grab header data (node and connection counts)
    sourceText = nextToken(sourceText, token, &lineEnd);
    numNodes = atof(token);

    sourceText = nextToken(sourceText, token, &lineEnd);
    numConnections = atof(token);

    if (nodes.size() == 0) {
        LOG("initializing nodes vector (total %d)", numNodes);
        nodes.reserve(numNodes);
        nodes.resize(NUM_ASNS_AT_TOP);
        //LOG("nodes.size: %ld", nodes.size());
    }

    int missingNodes = 0;
    for (int i = 0; i < numNodes; i++) {
        // Grab asn
        sourceText = nextToken(sourceText, token, &lineEnd);

        // check for matching existing node
        NodePointer node = nodesByAsn[token];

        if(node) {
            // already thre, just mark as active
            node->timelineActive = true;
        }
        else {
            // Not there, create
            missingNodes++;

            node = NodePointer(new Node());
            node->asn = token;
            node->type = AS_UNKNOWN;
            node->timelineActive = true;

            //is it a special node?
            bool needInsert = false;
            for (int i=0; i<NUM_ASNS_AT_TOP; i++) {
                if (strcmp(token, ASNS_AT_TOP[i]) == 0) {
                    node->index = i;
                    needInsert = true;
                    //LOG("found special at index %d", node->index);
                    break;
                }
            }

            if (needInsert) {
                nodes[node->index] = node;
            } else {
                //regular nodes can just be appended.
                node->index = nodes.size();
                nodes.push_back(node);
            }
            nodesByAsn[node->asn] = node;
        }

        // Refill data that is unique to a particualar timeline position
        sourceText = nextToken(sourceText, token, &lineEnd);
        if(node) {
            node->importance = atof(token);
        }
        sourceText = nextToken(sourceText, token, &lineEnd);
        if(node) {
            node->positionX = atof(token);
        }
        sourceText = nextToken(sourceText, token, &lineEnd);
        if(node) {
            node->positionY = atof(token);
        }

        if(node && firstLoad) {
            node->defaultPositionX = node->positionX;
            node->defaultPositionY = node->positionY;
            node->defaultImportance = node->importance;
            node->activeDefault = true;
        }
    }

    // Load connections
    for (int i = 0; i < numConnections; i++) {
        ConnectionPointer connection(new Connection());

        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->first = nodesByAsn[token];
        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->second = nodesByAsn[token];

        if (connection->first && connection->second) {
            connection->first->connections.push_back(connection);
            connection->second->connections.push_back(connection);
            connections.push_back(connection);
        }
    }

    if(firstLoad) {
        defaultConnections = connections;
    }

    LOG("loaded data: %d nodes (this load), %d nodes (total), %d connections", missingNodes, (int)(nodes.size()), numConnections);

    visualization->activate(nodes);

    createNodeBoxes();
}

void MapData::loadFromAttrString(const std::string& json){
    std::map<std::string, int> asTypeDict;
    asTypeDict["abstained"] = AS_UNKNOWN;
    asTypeDict["t1"] = AS_T1;
    asTypeDict["t2"] = AS_T2;
    asTypeDict["comp"] = AS_COMP;
    asTypeDict["edu"] = AS_EDU;
    asTypeDict["ix"] = AS_IX;
    asTypeDict["nic"] = AS_NIC;

    std::map<int, std::string> friendlyTypeStrings;
    friendlyTypeStrings[(int)AS_UNKNOWN] = "Unknown Network Type";
    friendlyTypeStrings[(int)AS_T1] = "Large ISP";
    friendlyTypeStrings[(int)AS_T2] = "Small ISP";
    friendlyTypeStrings[(int)AS_COMP] = "Organization Network";
    friendlyTypeStrings[(int)AS_EDU] = "University";
    friendlyTypeStrings[(int)AS_IX] = "Internet Exchange Point";
    friendlyTypeStrings[(int)AS_NIC] = "Network Information Center";

    std::vector<std::string> lines;
    split(lines, json, "\n");

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

        std::string line = lines[i];
        std::vector<std::string> aDesc;
        split(aDesc, line, "\t");
        NodePointer node = nodesByAsn[aDesc[0]];

        if(node){

            node->type = asTypeDict[aDesc[7]];
            node->typeString = friendlyTypeStrings[node->type];
            node->rawTextDescription = aDesc[1];
        }
    }

//    NSLog(@"attr load : %.2fms", ([NSDate timeIntervalSinceReferenceDate] - start) * 1000.0f);

}

void MapData::loadASInfo(const std::string& json){

    Json::Value root;
    Json::Reader reader;
    bool success = reader.parse(json, root);
    if(success) {
        std::vector<std::string> members = root.getMemberNames();
        for (unsigned int i = 0; i < members.size(); i++) {
            NodePointer node = nodesByAsn[members[i]];
            if (node) {
                Json::Value as = root[members[i]];
//                node->name = as[1].asString();
//                node->rawTextDescription = as[5].asString();
//                node->dateRegistered = as[3].asString();
//                node->address = as[7].asString();
//                node->city = as[8].asString();
//                node->state = as[9].asString();
//                node->postalCode = as[10].asString();
//                node->country = as[11].asString();
//                node->hasLatLong = true;
//                node->latitude = as[12].asFloat()*2.0*3.14159/360.0;
//                node->longitude = as[13].asFloat()*2.0*3.14159/360.0;

                node->rawTextDescription = as[0].asString();
                node->hasLatLong = true;
                node->latitude = as[1].asFloat()*2.0*3.14159/360.0;
                node->longitude = as[2].asFloat()*2.0*3.14159/360.0;
            }
        }
    }
}

void MapData::loadUnified(const std::string& text) {
    const char* sourceText = text.c_str();

    char token[MAX_TOKEN_SIZE];
    bool lineEnd;
    int numNodes, numConnections;

    // Grab header data (node and connection counts)
    sourceText = nextToken(sourceText, token, &lineEnd);
    numNodes = atof(token);

    sourceText = nextToken(sourceText, token, &lineEnd);
    numConnections = atof(token);

    nodes.reserve(numNodes);

    for (int i = 0; i < numNodes; i++) {
        NodePointer node = NodePointer(new Node());
        node->timelineActive = true;
        node->activeDefault = true;

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->asn = token;

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        if(token[0] != '?') {
            node->rawTextDescription = token;
        }

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->type = atoi(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->hasLatLong = atoi(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->latitude = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->longitude = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->positionX = node->defaultPositionX = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->positionY = node->defaultPositionY = atof(token);

        sourceText = nextToken(sourceText, token, &lineEnd, '\t');
        node->importance = node->defaultImportance = atof(token);

        assert(lineEnd);

        node->index = nodes.size();
        nodes.push_back(node);
        nodesByAsn[node->asn] = node;
    }

    // Load connections
    for (int i = 0; i < numConnections; i++) {
        ConnectionPointer connection(new Connection());

        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->first = nodesByAsn[token];
        sourceText = nextToken(sourceText, token, &lineEnd);
        connection->second = nodesByAsn[token];

        if (connection->first && connection->second) {
            connection->first->connections.push_back(connection);
            connection->second->connections.push_back(connection);
            connections.push_back(connection);
        }
    }

    defaultConnections = connections;

    LOG("loaded default data: %d nodes, %d connections", (int)(nodes.size()), numConnections);

    visualization->activate(nodes);

    createNodeBoxes();
}

void MapData::createNodeBoxes() {
    boxesForNodes.erase(boxesForNodes.begin(), boxesForNodes.end());

    for (int k = 0; k < numberOfCellsZ; k++) {
        float z = IndexBoxMinZ + boxSizeZWithoutOverlap*k;
        for (int j = 0; j < numberOfCellsY; j++) {
            float y = IndexBoxMinY + boxSizeYWithoutOverlap*j;
            for(int i = 0; i < numberOfCellsX; i++) {
                float x = IndexBoxMinX + boxSizeXWithoutOverlap*i;
                IndexBoxPointer box = IndexBoxPointer(new IndexBox());
                box->setCenter(Point3(x+boxSizeXWithoutOverlap/2, y+boxSizeYWithoutOverlap/2, z+boxSizeZWithoutOverlap/2));
                box->setMinCorner(Point3(x, y, z));
                box->setMaxCorner(Point3(x+boxSizeXWithoutOverlap, y+boxSizeYWithoutOverlap, z+boxSizeZWithoutOverlap));
                boxesForNodes.push_back(box);
            }
        }
    }

    for (unsigned int i = 0; i < nodes.size(); i++) {
        NodePointer ptrNode = nodes.at(i);
        if(ptrNode->isActive()) {
            Point3 pos = visualization->nodePosition(ptrNode);
            IndexBoxPointer box = indexBoxForPoint(pos);
            box->indices.insert(i);
        }
    }
}

IndexBoxPointer MapData::indexBoxForPoint(const Point3& point) {

    int posX = (int)fabsf((point.getX() + fabsf(IndexBoxMinX))/boxSizeXWithoutOverlap);
    int posY = (int)fabsf((point.getY() + fabsf(IndexBoxMinY))/boxSizeYWithoutOverlap);
    int posZ = (int)fabsf((point.getZ() + fabsf(IndexBoxMinZ))/boxSizeZWithoutOverlap);
    int posInArray = posX + (fabsf(IndexBoxMinX) + fabsf(IndexBoxMaxX))/boxSizeXWithoutOverlap*posY + (fabsf(IndexBoxMinX) + fabsf(IndexBoxMaxX))/boxSizeXWithoutOverlap*(fabsf(IndexBoxMinY)+fabsf(IndexBoxMaxY))/boxSizeYWithoutOverlap*posZ;

    return boxesForNodes[posInArray];
}

void MapData::dumpUnified(void) {
    std::ofstream out("/Users/nigel/Downloads/unified.txt");
    out << nodes.size() << std::endl;
    out << connections.size() << std::endl;

    for(int i = 0; i < nodes.size(); i++) {
        std::string desc = nodes[i]->rawTextDescription;
        if(desc.length() == 0) {
            desc = "?";
        }

        out << nodes[i]->asn << "\t"
            << desc << "\t"
            << nodes[i]->type << "\t"
            << nodes[i]->hasLatLong << "\t"
            << nodes[i]->latitude << "\t"
            << nodes[i]->longitude << "\t"
            << nodes[i]->positionX << "\t"
            << nodes[i]->positionY << "\t"
            << nodes[i]->importance << "\t" << std::endl;
    }

    for(int i = 0; i < connections.size(); i++) {
        out << connections[i]->first->index << " " << connections[i]->second->index << std::endl;
    }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMatrix4x4.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkMatrix4x4.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"

#include <stdlib.h>
#include <math.h>

vtkCxxRevisionMacro(vtkMatrix4x4, "1.61");
vtkStandardNewMacro(vtkMatrix4x4);

// Useful for viewing a double[16] as a double[4][4]
typedef double (*SqMatPtr)[4];

//----------------------------------------------------------------------------
void vtkMatrix4x4::Zero(double Elements[16])
{
  SqMatPtr elem  = (SqMatPtr)Elements;
  int i,j;
  for (i = 0; i < 4; i++)
    {
    for (j = 0; j < 4; j++)
      {
      elem[i][j] = 0.0;
      }
    }
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::Identity(double Elements[16])
{
  Elements[0] = Elements[5] = Elements[10] = Elements[15] = 1.0;
  Elements[1] = Elements[2] = Elements[3] = Elements[4] =
    Elements[6] = Elements[7] = Elements[8] = Elements[9] =
    Elements[11] = Elements[12] = Elements[13] = Elements[14] = 0.0;
}

//----------------------------------------------------------------------------
template<class T1, class T2, class T3>
void vtkMatrixMultiplyPoint(T1 elem[16], T2 in[4], T3 out[4])
{
  T3 v1 = in[0];
  T3 v2 = in[1];
  T3 v3 = in[2];
  T3 v4 = in[3];

  out[0] = v1*elem[0]  + v2*elem[1]  + v3*elem[2]  + v4*elem[3];
  out[1] = v1*elem[4]  + v2*elem[5]  + v3*elem[6]  + v4*elem[7];
  out[2] = v1*elem[8]  + v2*elem[9]  + v3*elem[10] + v4*elem[11];
  out[3] = v1*elem[12] + v2*elem[13] + v3*elem[14] + v4*elem[15];
}

//----------------------------------------------------------------------------
// Multiply this matrix by a point (in homogeneous coordinates).
// and return the result in result. The in[4] and result[4]
// arrays must both be allocated but they can be the same array.
void vtkMatrix4x4::MultiplyPoint(const double Elements[16],
                                 const float in[4], float result[4])
{
  vtkMatrixMultiplyPoint(Elements,in,result);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::MultiplyPoint(const double Elements[16],
                                 const double in[4], double result[4])
{
  vtkMatrixMultiplyPoint(Elements,in,result);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::PointMultiply(const double Elements[16],
                                 const float in[4], float result[4])
{
  double newElements[16];
  vtkMatrix4x4::Transpose(Elements,newElements);
  vtkMatrix4x4::MultiplyPoint(newElements,in,result);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::PointMultiply(const double Elements[16],
                                 const double in[4], double result[4])
{
  double newElements[16];
  vtkMatrix4x4::Transpose(Elements,newElements);
  vtkMatrix4x4::MultiplyPoint(newElements,in,result);
}

//----------------------------------------------------------------------------
// Multiplies matrices a and b and stores the result in c.
void vtkMatrix4x4::Multiply4x4(const double a[16], const double b[16],
                               double c[16])
{
  SqMatPtr aMat = (SqMatPtr) a;
  SqMatPtr bMat = (SqMatPtr) b;
  SqMatPtr cMat = (SqMatPtr) c;
  int i, k;
  double Accum[4][4];

  for (i = 0; i < 4; i++)
    {
    for (k = 0; k < 4; k++)
      {
      Accum[i][k] = aMat[i][0] * bMat[0][k] +
                    aMat[i][1] * bMat[1][k] +
                    aMat[i][2] * bMat[2][k] +
                    aMat[i][3] * bMat[3][k];
      }
    }

  // Copy to final dest
  for (i = 0; i < 4; i++)
    {
    cMat[i][0] = Accum[i][0];
    cMat[i][1] = Accum[i][1];
    cMat[i][2] = Accum[i][2];
    cMat[i][3] = Accum[i][3];
    }

}

//----------------------------------------------------------------------------
// Matrix Inversion (adapted from Richard Carling in "Graphics Gems,"
// Academic Press, 1990).
void vtkMatrix4x4::Invert(const double inElements[16],
                          double outElements[16])
{
  SqMatPtr outElem = (SqMatPtr)outElements;

  // inverse( original_matrix, inverse_matrix )
  // calculate the inverse of a 4x4 matrix
  //
  //     -1
  //     A  = ___1__ adjoint A
  //         det A
  //

  int i, j;
  double det;

  // calculate the 4x4 determinent
  // if the determinent is zero,
  // then the inverse matrix is not unique.

  det = vtkMatrix4x4::Determinant(inElements);
  if ( det == 0.0 )
    {
    vtkGenericWarningMacro(<< "Singular matrix, no inverse!" );
    return;
    }

  // calculate the adjoint matrix
  vtkMatrix4x4::Adjoint(inElements, outElements );

  // scale the adjoint matrix to get the inverse
  for (i=0; i<4; i++)
    {
    for(j=0; j<4; j++)
      {
      outElem[i][j] = outElem[i][j] / det;
      }
    }
}

//----------------------------------------------------------------------------
double vtkMatrix4x4::Determinant(const double Elements[16])
{
  SqMatPtr elem = (SqMatPtr)Elements;

  double a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;

  // assign to individual variable names to aid selecting
  //  correct elements

  a1 = elem[0][0]; b1 = elem[0][1];
  c1 = elem[0][2]; d1 = elem[0][3];

  a2 = elem[1][0]; b2 = elem[1][1];
  c2 = elem[1][2]; d2 = elem[1][3];

  a3 = elem[2][0]; b3 = elem[2][1];
  c3 = elem[2][2]; d3 = elem[2][3];

  a4 = elem[3][0]; b4 = elem[3][1];
  c4 = elem[3][2]; d4 = elem[3][3];

  return a1 * vtkMath::Determinant3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4)
       - b1 * vtkMath::Determinant3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4)
       + c1 * vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4)
       - d1 * vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::Adjoint(const double inElements[16], double outElements[16])
{
  SqMatPtr inElem = (SqMatPtr) inElements;
  SqMatPtr outElem = (SqMatPtr) outElements;

  //
  //   adjoint( original_matrix, inverse_matrix )
  //
  //     calculate the adjoint of a 4x4 matrix
  //
  //      Let  a   denote the minor determinant of matrix A obtained by
  //           ij
  //
  //      deleting the ith row and jth column from A.
  //
  //                    i+j
  //     Let  b   = (-1)    a
  //          ij            ji
  //
  //    The matrix B = (b  ) is the adjoint of A
  //                     ij
  //
  double a1, a2, a3, a4, b1, b2, b3, b4;
  double c1, c2, c3, c4, d1, d2, d3, d4;

  // assign to individual variable names to aid
  // selecting correct values

  a1 = inElem[0][0]; b1 = inElem[0][1];
  c1 = inElem[0][2]; d1 = inElem[0][3];

  a2 = inElem[1][0]; b2 = inElem[1][1];
  c2 = inElem[1][2]; d2 = inElem[1][3];

  a3 = inElem[2][0]; b3 = inElem[2][1];
  c3 = inElem[2][2]; d3 = inElem[2][3];

  a4 = inElem[3][0]; b4 = inElem[3][1];
  c4 = inElem[3][2]; d4 = inElem[3][3];

  // row column labeling reversed since we transpose rows & columns

  outElem[0][0]  =
    vtkMath::Determinant3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
  outElem[1][0]  =
    - vtkMath::Determinant3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
  outElem[2][0]  =
    vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
  outElem[3][0]  =
    - vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);

  outElem[0][1]  =
    - vtkMath::Determinant3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
  outElem[1][1]  =
    vtkMath::Determinant3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
  outElem[2][1]  =
    - vtkMath::Determinant3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
  outElem[3][1]  =
    vtkMath::Determinant3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);

  outElem[0][2]  =
    vtkMath::Determinant3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
  outElem[1][2]  =
    - vtkMath::Determinant3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
  outElem[2][2]  =
    vtkMath::Determinant3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
  outElem[3][2]  =
    - vtkMath::Determinant3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);

  outElem[0][3]  =
    - vtkMath::Determinant3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
  outElem[1][3]  =
    vtkMath::Determinant3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
  outElem[2][3]  =
    - vtkMath::Determinant3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
  outElem[3][3]  =
    vtkMath::Determinant3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::DeepCopy(double Elements[16], const double newElements[16])
{
  for (int i = 0; i < 16; i++)
    {
    Elements[i] = newElements[i];
    }
}

//----------------------------------------------------------------------------
// Transpose the matrix and put it into out.
void vtkMatrix4x4::Transpose(const double inElements[16],
                              double outElements[16])
{
  SqMatPtr inElem = (SqMatPtr)inElements;
  SqMatPtr outElem = (SqMatPtr)outElements;
  int i, j;
  double temp;

  for (i=0; i<4; i++)
    {
    for(j=i; j<4; j++)
      {
      temp = inElem[i][j];
      outElem[i][j] = inElem[j][i];
      outElem[j][i] = temp;
      }
    }
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  int i, j;

  os << indent << "Elements:\n";
  for (i = 0; i < 4; i++)
    {
    os << indent << indent;
    for (j = 0; j < 4; j++)
      {
      os << this->Element[i][j] << " ";
      }
    os << "\n";
    }
}
<commit_msg>BUG: singular matrix should not force a warning<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMatrix4x4.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkMatrix4x4.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"

#include <stdlib.h>
#include <math.h>

vtkCxxRevisionMacro(vtkMatrix4x4, "1.62");
vtkStandardNewMacro(vtkMatrix4x4);

// Useful for viewing a double[16] as a double[4][4]
typedef double (*SqMatPtr)[4];

//----------------------------------------------------------------------------
void vtkMatrix4x4::Zero(double Elements[16])
{
  SqMatPtr elem  = (SqMatPtr)Elements;
  int i,j;
  for (i = 0; i < 4; i++)
    {
    for (j = 0; j < 4; j++)
      {
      elem[i][j] = 0.0;
      }
    }
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::Identity(double Elements[16])
{
  Elements[0] = Elements[5] = Elements[10] = Elements[15] = 1.0;
  Elements[1] = Elements[2] = Elements[3] = Elements[4] =
    Elements[6] = Elements[7] = Elements[8] = Elements[9] =
    Elements[11] = Elements[12] = Elements[13] = Elements[14] = 0.0;
}

//----------------------------------------------------------------------------
template<class T1, class T2, class T3>
void vtkMatrixMultiplyPoint(T1 elem[16], T2 in[4], T3 out[4])
{
  T3 v1 = in[0];
  T3 v2 = in[1];
  T3 v3 = in[2];
  T3 v4 = in[3];

  out[0] = v1*elem[0]  + v2*elem[1]  + v3*elem[2]  + v4*elem[3];
  out[1] = v1*elem[4]  + v2*elem[5]  + v3*elem[6]  + v4*elem[7];
  out[2] = v1*elem[8]  + v2*elem[9]  + v3*elem[10] + v4*elem[11];
  out[3] = v1*elem[12] + v2*elem[13] + v3*elem[14] + v4*elem[15];
}

//----------------------------------------------------------------------------
// Multiply this matrix by a point (in homogeneous coordinates).
// and return the result in result. The in[4] and result[4]
// arrays must both be allocated but they can be the same array.
void vtkMatrix4x4::MultiplyPoint(const double Elements[16],
                                 const float in[4], float result[4])
{
  vtkMatrixMultiplyPoint(Elements,in,result);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::MultiplyPoint(const double Elements[16],
                                 const double in[4], double result[4])
{
  vtkMatrixMultiplyPoint(Elements,in,result);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::PointMultiply(const double Elements[16],
                                 const float in[4], float result[4])
{
  double newElements[16];
  vtkMatrix4x4::Transpose(Elements,newElements);
  vtkMatrix4x4::MultiplyPoint(newElements,in,result);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::PointMultiply(const double Elements[16],
                                 const double in[4], double result[4])
{
  double newElements[16];
  vtkMatrix4x4::Transpose(Elements,newElements);
  vtkMatrix4x4::MultiplyPoint(newElements,in,result);
}

//----------------------------------------------------------------------------
// Multiplies matrices a and b and stores the result in c.
void vtkMatrix4x4::Multiply4x4(const double a[16], const double b[16],
                               double c[16])
{
  SqMatPtr aMat = (SqMatPtr) a;
  SqMatPtr bMat = (SqMatPtr) b;
  SqMatPtr cMat = (SqMatPtr) c;
  int i, k;
  double Accum[4][4];

  for (i = 0; i < 4; i++)
    {
    for (k = 0; k < 4; k++)
      {
      Accum[i][k] = aMat[i][0] * bMat[0][k] +
                    aMat[i][1] * bMat[1][k] +
                    aMat[i][2] * bMat[2][k] +
                    aMat[i][3] * bMat[3][k];
      }
    }

  // Copy to final dest
  for (i = 0; i < 4; i++)
    {
    cMat[i][0] = Accum[i][0];
    cMat[i][1] = Accum[i][1];
    cMat[i][2] = Accum[i][2];
    cMat[i][3] = Accum[i][3];
    }

}

//----------------------------------------------------------------------------
// Matrix Inversion (adapted from Richard Carling in "Graphics Gems,"
// Academic Press, 1990).
void vtkMatrix4x4::Invert(const double inElements[16],
                          double outElements[16])
{
  SqMatPtr outElem = (SqMatPtr)outElements;

  // inverse( original_matrix, inverse_matrix )
  // calculate the inverse of a 4x4 matrix
  //
  //     -1
  //     A  = ___1__ adjoint A
  //         det A
  //

  int i, j;
  double det;

  // calculate the 4x4 determinent
  // if the determinent is zero,
  // then the inverse matrix is not unique.

  det = vtkMatrix4x4::Determinant(inElements);
  if ( det == 0.0 )
    {
    return;
    }

  // calculate the adjoint matrix
  vtkMatrix4x4::Adjoint(inElements, outElements );

  // scale the adjoint matrix to get the inverse
  for (i=0; i<4; i++)
    {
    for(j=0; j<4; j++)
      {
      outElem[i][j] = outElem[i][j] / det;
      }
    }
}

//----------------------------------------------------------------------------
double vtkMatrix4x4::Determinant(const double Elements[16])
{
  SqMatPtr elem = (SqMatPtr)Elements;

  double a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;

  // assign to individual variable names to aid selecting
  //  correct elements

  a1 = elem[0][0]; b1 = elem[0][1];
  c1 = elem[0][2]; d1 = elem[0][3];

  a2 = elem[1][0]; b2 = elem[1][1];
  c2 = elem[1][2]; d2 = elem[1][3];

  a3 = elem[2][0]; b3 = elem[2][1];
  c3 = elem[2][2]; d3 = elem[2][3];

  a4 = elem[3][0]; b4 = elem[3][1];
  c4 = elem[3][2]; d4 = elem[3][3];

  return a1 * vtkMath::Determinant3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4)
       - b1 * vtkMath::Determinant3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4)
       + c1 * vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4)
       - d1 * vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::Adjoint(const double inElements[16], double outElements[16])
{
  SqMatPtr inElem = (SqMatPtr) inElements;
  SqMatPtr outElem = (SqMatPtr) outElements;

  //
  //   adjoint( original_matrix, inverse_matrix )
  //
  //     calculate the adjoint of a 4x4 matrix
  //
  //      Let  a   denote the minor determinant of matrix A obtained by
  //           ij
  //
  //      deleting the ith row and jth column from A.
  //
  //                    i+j
  //     Let  b   = (-1)    a
  //          ij            ji
  //
  //    The matrix B = (b  ) is the adjoint of A
  //                     ij
  //
  double a1, a2, a3, a4, b1, b2, b3, b4;
  double c1, c2, c3, c4, d1, d2, d3, d4;

  // assign to individual variable names to aid
  // selecting correct values

  a1 = inElem[0][0]; b1 = inElem[0][1];
  c1 = inElem[0][2]; d1 = inElem[0][3];

  a2 = inElem[1][0]; b2 = inElem[1][1];
  c2 = inElem[1][2]; d2 = inElem[1][3];

  a3 = inElem[2][0]; b3 = inElem[2][1];
  c3 = inElem[2][2]; d3 = inElem[2][3];

  a4 = inElem[3][0]; b4 = inElem[3][1];
  c4 = inElem[3][2]; d4 = inElem[3][3];

  // row column labeling reversed since we transpose rows & columns

  outElem[0][0]  =
    vtkMath::Determinant3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
  outElem[1][0]  =
    - vtkMath::Determinant3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
  outElem[2][0]  =
    vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
  outElem[3][0]  =
    - vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);

  outElem[0][1]  =
    - vtkMath::Determinant3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
  outElem[1][1]  =
    vtkMath::Determinant3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
  outElem[2][1]  =
    - vtkMath::Determinant3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
  outElem[3][1]  =
    vtkMath::Determinant3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);

  outElem[0][2]  =
    vtkMath::Determinant3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
  outElem[1][2]  =
    - vtkMath::Determinant3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
  outElem[2][2]  =
    vtkMath::Determinant3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
  outElem[3][2]  =
    - vtkMath::Determinant3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);

  outElem[0][3]  =
    - vtkMath::Determinant3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
  outElem[1][3]  =
    vtkMath::Determinant3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
  outElem[2][3]  =
    - vtkMath::Determinant3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
  outElem[3][3]  =
    vtkMath::Determinant3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::DeepCopy(double Elements[16], const double newElements[16])
{
  for (int i = 0; i < 16; i++)
    {
    Elements[i] = newElements[i];
    }
}

//----------------------------------------------------------------------------
// Transpose the matrix and put it into out.
void vtkMatrix4x4::Transpose(const double inElements[16],
                              double outElements[16])
{
  SqMatPtr inElem = (SqMatPtr)inElements;
  SqMatPtr outElem = (SqMatPtr)outElements;
  int i, j;
  double temp;

  for (i=0; i<4; i++)
    {
    for(j=i; j<4; j++)
      {
      temp = inElem[i][j];
      outElem[i][j] = inElem[j][i];
      outElem[j][i] = temp;
      }
    }
}

//----------------------------------------------------------------------------
void vtkMatrix4x4::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  int i, j;

  os << indent << "Elements:\n";
  for (i = 0; i < 4; i++)
    {
    os << indent << indent;
    for (j = 0; j < 4; j++)
      {
      os << this->Element[i][j] << " ";
      }
    os << "\n";
    }
}
<|endoftext|>


<commit_before><commit_msg>Cleaning up code.<commit_after><|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is [Open Source Virtual Machine.].
 *
 * The Initial Developer of the Original Code is
 * Adobe System Incorporated.
 * Portions created by the Initial Developer are Copyright (C) 2004-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Adobe AS3 Team
 *   leon.sha@sun.com
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>

#include "MMgc.h"
#include "GCDebug.h"
#include "GC.h"

#include <sys/mman.h>

#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif // !defined(MAP_ANONYMOUS) && defined(MAP_ANON)

#if defined(MEMORY_INFO) && defined(AVMPLUS_UNIX)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
#endif

// avmplus standalone uses UNIX
#ifdef _MAC
#define MAP_ANONYMOUS MAP_ANON
#endif

#ifdef SOLARIS
#include <ucontext.h>
#include <dlfcn.h>
extern "C" caddr_t _getfp(void);
typedef caddr_t maddr_ptr;
#else
typedef void *maddr_ptr;
#endif

namespace MMgc
{
#ifndef USE_MMAP
	void *aligned_malloc(size_t size, size_t align_size, GCMallocFuncPtr m_malloc)
	{
		char *ptr, *ptr2, *aligned_ptr;
		int align_mask = align_size - 1;

		int alloc_size = size + align_size + sizeof(int);
		ptr=(char *)m_malloc(alloc_size);

		if(ptr==NULL) return(NULL);

		ptr2 = ptr + sizeof(int);
		aligned_ptr = ptr2 + (align_size - ((size_t)ptr2 & align_mask));

		ptr2 = aligned_ptr - sizeof(int);
		*((int *)ptr2)=(int)(aligned_ptr - ptr);

		return(aligned_ptr);
	}

	void aligned_free(void *ptr, GCFreeFuncPtr m_free)
	{
		int *ptr2=(int *)ptr - 1;
		char *unaligned_ptr = (char*) ptr - *ptr2;
		m_free(unaligned_ptr);
	}
#endif /* !USE_MMAP */

#ifdef USE_MMAP
	int GCHeap::vmPageSize()
	{
		long v = sysconf(_SC_PAGESIZE);
		return v;
	}

	void* GCHeap::ReserveCodeMemory(void* address,
									size_t size)
	{
		return (char*) mmap((maddr_ptr)address,
							size,
							PROT_READ | PROT_WRITE,
							MAP_PRIVATE | MAP_ANONYMOUS,
							-1, 0);
	}

	void GCHeap::ReleaseCodeMemory(void* address,
								   size_t size)
	{
		if (munmap((maddr_ptr)address, size) != 0)
			GCAssert(false);
	}

	bool GCHeap::SetGuardPage(void *address)
	{
		return false;
	}
#endif /* USE_MMAP */

#ifdef AVMPLUS_JIT_READONLY
	/**
	 * SetExecuteBit changes the page access protections on a block of pages,
	 * to make JIT-ted code executable or not.
	 *
	 * If executableFlag is true, the memory is made executable and read-only.
	 *
	 * If executableFlag is false, the memory is made non-executable and
	 * read-write.
	 */
	void GCHeap::SetExecuteBit(void *address,
							   size_t size,
							   bool executableFlag)
	{
		// Should use vmPageSize() or kNativePageSize here.
		// But this value is hard coded to 4096 if we don't use mmap.
		int bitmask = sysconf(_SC_PAGESIZE) - 1;

		// mprotect requires that the addresses be aligned on page boundaries
		void *endAddress = (void*) ((char*)address + size);
		void *beginPage = (void*) ((size_t)address & ~bitmask);
		void *endPage   = (void*) (((size_t)endAddress + bitmask) & ~bitmask);
		size_t sizePaged = (size_t)endPage - (size_t)beginPage;

#ifdef DEBUG
		int retval =
#endif
		  mprotect((maddr_ptr)beginPage, sizePaged,
			   executableFlag ? (PROT_READ|PROT_EXEC) : (PROT_READ|PROT_WRITE|PROT_EXEC));

		GCAssert(retval == 0);
	}
#endif /* AVMPLUS_JIT_READONLY */

#ifdef USE_MMAP
	void* GCHeap::CommitCodeMemory(void* address,
								  size_t size)
	{
		void* res;
		if (size == 0)
			size = GCHeap::kNativePageSize;  // default of one page

#ifdef AVMPLUS_JIT_READONLY
		mmap((maddr_ptr)address,
			 size,
			 PROT_READ | PROT_WRITE,
			 MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
			 -1, 0);
#else
		mmap((maddr_ptr)address,
			 size,
			 PROT_READ | PROT_WRITE | PROT_EXEC,
			 MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
			 -1, 0);
#endif /* AVMPLUS_JIT_READONLY */
		res = address;

		if (res == address)
			address = (void*)( (uintptr)address + size );
		else
			address = 0;
		return address;
	}

	void* GCHeap::DecommitCodeMemory(void* address,
									 size_t size)
	{
		if (size == 0)
			size = GCHeap::kNativePageSize;  // default of one page

		// release and re-reserve it
		ReleaseCodeMemory(address, size);
		address = ReserveCodeMemory(address, size);
		return address;
	}
#else
	int GCHeap::vmPageSize()
	{
		return 4096;
	}

	void* GCHeap::ReserveCodeMemory(void* address,
									size_t size)
	{
		return aligned_malloc(size, 4096, m_malloc);
	}

	void GCHeap::ReleaseCodeMemory(void* address,
								   size_t size)
	{
		aligned_free(address, m_free);
	}

	bool GCHeap::SetGuardPage(void *address)
	{
		return false;
	}

	void* GCHeap::CommitCodeMemory(void* address,
								   size_t size)
	{
		return address;
	}
	void* GCHeap::DecommitCodeMemory(void* address,
									 size_t size)
	{
		return address;
	}
#endif /* USE_MMAP */

#ifdef USE_MMAP
	char* GCHeap::ReserveMemory(char *address, size_t size)
	{
		char *addr = (char*)mmap((maddr_ptr)address,
					 size,
					 PROT_READ | PROT_WRITE,
					 MAP_PRIVATE | MAP_ANONYMOUS,
					 -1, 0);
		if (addr == MAP_FAILED) {
			return NULL;
		}
		if(address && address != addr) {
			// behave like windows and fail if we didn't get the right address
			ReleaseMemory(addr, size);
			return NULL;
		}
		return addr;
	}

	bool GCHeap::CommitMemory(char *address, size_t size)
	{
		char *addr = (char*)mmap(address,
					size,
					PROT_READ | PROT_WRITE,
			                MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
					-1, 0);
		GCAssert(addr == address);
		return addr == address;
	}

	bool GCHeap::DecommitMemory(char *address, size_t size)
	{
		ReleaseMemory(address, size);
		// re-reserve it
		char *addr = (char*)mmap((maddr_ptr)address,
					 size,
					 PROT_NONE,
					 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
					 -1, 0);
		GCAssert(addr == address);
		return addr == address;
	}

	bool GCHeap::CommitMemoryThatMaySpanRegions(char *address, size_t size)
	{
		return CommitMemory(address, size);
	}

	bool GCHeap::DecommitMemoryThatMaySpanRegions(char *address, size_t size)
	{
		return DecommitMemory(address, size);
	}

	void GCHeap::ReleaseMemory(char *address, size_t size)
	{
#ifdef DEBUG
		int result =
#endif
		munmap((maddr_ptr)address, size);
		GCAssert(result == 0);
	}
#else
	char* GCHeap::AllocateMemory(size_t size)
	{
		return (char *) aligned_malloc(size, 4096, m_malloc);
	}

	void GCHeap::ReleaseMemory(char *address)
	{
		aligned_free(address, m_free);
	}
#endif

#ifdef MEMORY_INFO
	void GetInfoFromPC(int pc, char *buff, int buffSize)
	{
#ifdef AVMPLUS_UNIX
		Dl_info dlip;
		dladdr((void *const)pc, &dlip);
		sprintf(buff, "0x%08x:%s", pc, dlip.dli_sname);
#else
		sprintf(buff, "0x%x", pc);
#endif
	}

#ifdef MMGC_SPARC
	void GetStackTrace(int *trace, int len, int skip)
	{
	  // TODO for sparc.
		GCAssert(false);

	}
#endif

#ifdef MMGC_PPC
	void GetStackTrace(int *trace, int len, int skip)
	{
	  register int stackp;
	  int pc;
	  asm("mr %0,r1" : "=r" (stackp));
	  while(skip--) {
	    stackp = *(int*)stackp;
	  }
	  int i=0;
	  // save space for 0 terminator
	  len--;
	  while(i<len && stackp) {
	    pc = *((int*)stackp+2);
	    trace[i++]=pc;
	    stackp = *(int*)stackp;
	  }
	  trace[i] = 0;
	}
#endif

#ifdef MMGC_IA32
	void GetStackTrace(int *trace, int len, int skip)
	{
		void **ebp;
#ifdef SOLARIS
		ebp = (void **)_getfp();
#else
		asm("mov %%ebp, %0" : "=r" (ebp));
#endif

		while(skip-- && *ebp)
		{
			ebp = (void**)(*ebp);
		}

		/* save space for 0 terminator */
		len--;

		int i = 0;

		while (i < len && *ebp)
		{
			/* store the current frame pointer */
			trace[i++] = *((int*) ebp + 1);
			/* get the next frame pointer */
			ebp = (void**)(*ebp);
		}

		trace[i] = 0;
	}
#endif

#ifdef MMGC_ARM
	void GetStackTrace(int *trace, int len, int skip) {}
#endif

#endif
}
<commit_msg>Bug 415326 The mmap option in mprotect is set wrong in GCHeapUnix.cpp. treilly: review+<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is [Open Source Virtual Machine.].
 *
 * The Initial Developer of the Original Code is
 * Adobe System Incorporated.
 * Portions created by the Initial Developer are Copyright (C) 2004-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Adobe AS3 Team
 *   leon.sha@sun.com
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>

#include "MMgc.h"
#include "GCDebug.h"
#include "GC.h"

#include <sys/mman.h>

#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif // !defined(MAP_ANONYMOUS) && defined(MAP_ANON)

#if defined(MEMORY_INFO) && defined(AVMPLUS_UNIX)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
#endif

// avmplus standalone uses UNIX
#ifdef _MAC
#define MAP_ANONYMOUS MAP_ANON
#endif

#ifdef SOLARIS
#include <ucontext.h>
#include <dlfcn.h>
extern "C" caddr_t _getfp(void);
typedef caddr_t maddr_ptr;
#else
typedef void *maddr_ptr;
#endif

namespace MMgc
{
#ifndef USE_MMAP
	void *aligned_malloc(size_t size, size_t align_size, GCMallocFuncPtr m_malloc)
	{
		char *ptr, *ptr2, *aligned_ptr;
		int align_mask = align_size - 1;

		int alloc_size = size + align_size + sizeof(int);
		ptr=(char *)m_malloc(alloc_size);

		if(ptr==NULL) return(NULL);

		ptr2 = ptr + sizeof(int);
		aligned_ptr = ptr2 + (align_size - ((size_t)ptr2 & align_mask));

		ptr2 = aligned_ptr - sizeof(int);
		*((int *)ptr2)=(int)(aligned_ptr - ptr);

		return(aligned_ptr);
	}

	void aligned_free(void *ptr, GCFreeFuncPtr m_free)
	{
		int *ptr2=(int *)ptr - 1;
		char *unaligned_ptr = (char*) ptr - *ptr2;
		m_free(unaligned_ptr);
	}
#endif /* !USE_MMAP */

#ifdef USE_MMAP
	int GCHeap::vmPageSize()
	{
		long v = sysconf(_SC_PAGESIZE);
		return v;
	}

	void* GCHeap::ReserveCodeMemory(void* address,
									size_t size)
	{
		return (char*) mmap((maddr_ptr)address,
							size,
							PROT_READ | PROT_WRITE,
							MAP_PRIVATE | MAP_ANONYMOUS,
							-1, 0);
	}

	void GCHeap::ReleaseCodeMemory(void* address,
								   size_t size)
	{
		if (munmap((maddr_ptr)address, size) != 0)
			GCAssert(false);
	}

	bool GCHeap::SetGuardPage(void *address)
	{
		return false;
	}
#endif /* USE_MMAP */

#ifdef AVMPLUS_JIT_READONLY
	/**
	 * SetExecuteBit changes the page access protections on a block of pages,
	 * to make JIT-ted code executable or not.
	 *
	 * If executableFlag is true, the memory is made executable and read-only.
	 *
	 * If executableFlag is false, the memory is made non-executable and
	 * read-write.
	 */
	void GCHeap::SetExecuteBit(void *address,
							   size_t size,
							   bool executableFlag)
	{
		// Should use vmPageSize() or kNativePageSize here.
		// But this value is hard coded to 4096 if we don't use mmap.
		int bitmask = sysconf(_SC_PAGESIZE) - 1;

		// mprotect requires that the addresses be aligned on page boundaries
		void *endAddress = (void*) ((char*)address + size);
		void *beginPage = (void*) ((size_t)address & ~bitmask);
		void *endPage   = (void*) (((size_t)endAddress + bitmask) & ~bitmask);
		size_t sizePaged = (size_t)endPage - (size_t)beginPage;

#ifdef DEBUG
		int retval =
#endif
		  mprotect((maddr_ptr)beginPage, sizePaged,
			   executableFlag ? (PROT_READ|PROT_WRITE|PROT_EXEC) : (PROT_READ|PROT_WRITE));

		GCAssert(retval == 0);
	}
#endif /* AVMPLUS_JIT_READONLY */

#ifdef USE_MMAP
	void* GCHeap::CommitCodeMemory(void* address,
								  size_t size)
	{
		void* res;
		if (size == 0)
			size = GCHeap::kNativePageSize;  // default of one page

#ifdef AVMPLUS_JIT_READONLY
		mmap((maddr_ptr)address,
			 size,
			 PROT_READ | PROT_WRITE,
			 MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
			 -1, 0);
#else
		mmap((maddr_ptr)address,
			 size,
			 PROT_READ | PROT_WRITE | PROT_EXEC,
			 MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
			 -1, 0);
#endif /* AVMPLUS_JIT_READONLY */
		res = address;

		if (res == address)
			address = (void*)( (uintptr)address + size );
		else
			address = 0;
		return address;
	}

	void* GCHeap::DecommitCodeMemory(void* address,
									 size_t size)
	{
		if (size == 0)
			size = GCHeap::kNativePageSize;  // default of one page

		// release and re-reserve it
		ReleaseCodeMemory(address, size);
		address = ReserveCodeMemory(address, size);
		return address;
	}
#else
	int GCHeap::vmPageSize()
	{
		return 4096;
	}

	void* GCHeap::ReserveCodeMemory(void* address,
									size_t size)
	{
		return aligned_malloc(size, 4096, m_malloc);
	}

	void GCHeap::ReleaseCodeMemory(void* address,
								   size_t size)
	{
		aligned_free(address, m_free);
	}

	bool GCHeap::SetGuardPage(void *address)
	{
		return false;
	}

	void* GCHeap::CommitCodeMemory(void* address,
								   size_t size)
	{
		return address;
	}
	void* GCHeap::DecommitCodeMemory(void* address,
									 size_t size)
	{
		return address;
	}
#endif /* USE_MMAP */

#ifdef USE_MMAP
	char* GCHeap::ReserveMemory(char *address, size_t size)
	{
		char *addr = (char*)mmap((maddr_ptr)address,
					 size,
					 PROT_READ | PROT_WRITE,
					 MAP_PRIVATE | MAP_ANONYMOUS,
					 -1, 0);
		if (addr == MAP_FAILED) {
			return NULL;
		}
		if(address && address != addr) {
			// behave like windows and fail if we didn't get the right address
			ReleaseMemory(addr, size);
			return NULL;
		}
		return addr;
	}

	bool GCHeap::CommitMemory(char *address, size_t size)
	{
		char *addr = (char*)mmap(address,
					size,
					PROT_READ | PROT_WRITE,
			                MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
					-1, 0);
		GCAssert(addr == address);
		return addr == address;
	}

	bool GCHeap::DecommitMemory(char *address, size_t size)
	{
		ReleaseMemory(address, size);
		// re-reserve it
		char *addr = (char*)mmap((maddr_ptr)address,
					 size,
					 PROT_NONE,
					 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
					 -1, 0);
		GCAssert(addr == address);
		return addr == address;
	}

	bool GCHeap::CommitMemoryThatMaySpanRegions(char *address, size_t size)
	{
		return CommitMemory(address, size);
	}

	bool GCHeap::DecommitMemoryThatMaySpanRegions(char *address, size_t size)
	{
		return DecommitMemory(address, size);
	}

	void GCHeap::ReleaseMemory(char *address, size_t size)
	{
#ifdef DEBUG
		int result =
#endif
		munmap((maddr_ptr)address, size);
		GCAssert(result == 0);
	}
#else
	char* GCHeap::AllocateMemory(size_t size)
	{
		return (char *) aligned_malloc(size, 4096, m_malloc);
	}

	void GCHeap::ReleaseMemory(char *address)
	{
		aligned_free(address, m_free);
	}
#endif

#ifdef MEMORY_INFO
	void GetInfoFromPC(int pc, char *buff, int buffSize)
	{
#ifdef AVMPLUS_UNIX
		Dl_info dlip;
		dladdr((void *const)pc, &dlip);
		sprintf(buff, "0x%08x:%s", pc, dlip.dli_sname);
#else
		sprintf(buff, "0x%x", pc);
#endif
	}

#ifdef MMGC_SPARC
	void GetStackTrace(int *trace, int len, int skip)
	{
	  // TODO for sparc.
		GCAssert(false);

	}
#endif

#ifdef MMGC_PPC
	void GetStackTrace(int *trace, int len, int skip)
	{
	  register int stackp;
	  int pc;
	  asm("mr %0,r1" : "=r" (stackp));
	  while(skip--) {
	    stackp = *(int*)stackp;
	  }
	  int i=0;
	  // save space for 0 terminator
	  len--;
	  while(i<len && stackp) {
	    pc = *((int*)stackp+2);
	    trace[i++]=pc;
	    stackp = *(int*)stackp;
	  }
	  trace[i] = 0;
	}
#endif

#ifdef MMGC_IA32
	void GetStackTrace(int *trace, int len, int skip)
	{
		void **ebp;
#ifdef SOLARIS
		ebp = (void **)_getfp();
#else
		asm("mov %%ebp, %0" : "=r" (ebp));
#endif

		while(skip-- && *ebp)
		{
			ebp = (void**)(*ebp);
		}

		/* save space for 0 terminator */
		len--;

		int i = 0;

		while (i < len && *ebp)
		{
			/* store the current frame pointer */
			trace[i++] = *((int*) ebp + 1);
			/* get the next frame pointer */
			ebp = (void**)(*ebp);
		}

		trace[i] = 0;
	}
#endif

#ifdef MMGC_ARM
	void GetStackTrace(int *trace, int len, int skip) {}
#endif

#endif
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Realm 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 <algorithm>
#include <stdexcept>

#include <tightdb/util/assert.hpp>
#include <tightdb/util/utf8.hpp>
#include <tightdb/util/buffer.hpp>

#include "util.hpp"
#include "io_realm_internal_Util.h"

using namespace std;
using namespace tightdb;
using namespace tightdb::util;

void ThrowException(JNIEnv* env, ExceptionKind exception, std::string classStr, std::string itemStr)
{
    std::string message;
    jclass jExceptionClass = NULL;

    TR_ERR((env, "\njni: ThrowingException %d, %s, %s.\n", exception, classStr.c_str(), itemStr.c_str()));

    switch (exception) {
        case ClassNotFound:
            jExceptionClass = env->FindClass("java/lang/ClassNotFoundException");
            message = "Class '" + classStr + "' could not be located.";
            break;

        case NoSuchField:
            jExceptionClass = env->FindClass("java/lang/NoSuchFieldException");
            message = "Field '" + itemStr + "' could not be located in class io.realm." + classStr;
            break;

        case NoSuchMethod:
            jExceptionClass = env->FindClass("java/lang/NoSuchMethodException");
            message = "Method '" + itemStr + "' could not be located in class io.realm." + classStr;
            break;

        case IllegalArgument:
            jExceptionClass = env->FindClass("java/lang/IllegalArgumentException");
            message = "Illegal Argument: " + classStr;
            break;

        case TableInvalid:
            jExceptionClass = env->FindClass("java/lang/IllegalStateException");
            message = "Illegal State: " + classStr;
            break;

        case IOFailed:
            jExceptionClass = env->FindClass("io/realm/exceptions/RealmIOException");
            message = "Failed to open " + classStr + ". " + itemStr;
            break;

        case FileNotFound:
            jExceptionClass = env->FindClass("io/realm/exceptions/RealmIOException");
            message = "File not found: " + classStr + ".";
            break;

        case FileAccessError:
            jExceptionClass = env->FindClass("io/realm/exceptions/RealmIOException");
            message = "Failed to access: " + classStr + ". " + itemStr;
            break;

        case IndexOutOfBounds:
            jExceptionClass = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
            message = classStr;
            break;

        case UnsupportedOperation:
            jExceptionClass = env->FindClass("java/lang/UnsupportedOperationException");
            message = classStr;
            break;

        case OutOfMemory:
            jExceptionClass = env->FindClass("io/realm/internal/OutOfMemoryError");
            message = classStr + " " + itemStr;
            break;

        case Unspecified:
            jExceptionClass = env->FindClass("java/lang/RuntimeException");
            message = "Unspecified exception. " + classStr;
            break;

        case RuntimeError:
            jExceptionClass = env->FindClass("java/lang/RuntimeException");
            message = classStr;
            break;

        case RowInvalid:
            jExceptionClass = env->FindClass("java/lang/IllegalStateException");
            message = "Illegal State: " + classStr;
            break;
    }
    if (jExceptionClass != NULL)
        env->ThrowNew(jExceptionClass, message.c_str());
    else {
        TR_ERR((env, "\nERROR: Couldn't throw exception.\n"));
    }

    env->DeleteLocalRef(jExceptionClass);
}

jclass GetClass(JNIEnv* env, const char* classStr)
{
    jclass localRefClass = env->FindClass(classStr);
    if (localRefClass == NULL) {
        ThrowException(env, ClassNotFound, classStr);
        return NULL;
    }

    jclass myClass = reinterpret_cast<jclass>( env->NewGlobalRef(localRefClass) );
    env->DeleteLocalRef(localRefClass);
    return myClass;
}

void jprint(JNIEnv *env, char *txt)
{
#if 1
    static_cast<void>(env);
    fprintf(stderr, " -- JNI: %s", txt);  fflush(stderr);
#else
    static jclass myClass = GetClass(env, "io/realm/internal/Util");
    static jmethodID myMethod = env->GetStaticMethodID(myClass, "javaPrint", "(Ljava/lang/String;)V");
    if (myMethod)
        env->CallStaticVoidMethod(myClass, myMethod, to_jstring(env, txt));
    else
        ThrowException(env, NoSuchMethod, "Util", "javaPrint");
#endif
}

void jprintf(JNIEnv *env, const char *format, ...)
{
    va_list argptr;
    char buf[200];
    va_start(argptr, format);
    //vfprintf(stderr, format, argptr);
    vsnprintf(buf, 200, format, argptr);
    jprint(env, buf);
    va_end(argptr);
}

bool GetBinaryData(JNIEnv* env, jobject jByteBuffer, tightdb::BinaryData& bin)
{
    const char* data = static_cast<char*>(env->GetDirectBufferAddress(jByteBuffer));
    if (!data) {
        ThrowException(env, IllegalArgument, "ByteBuffer is invalid");
        return false;
    }
    jlong size = env->GetDirectBufferCapacity(jByteBuffer);
    if (size < 0) {
        ThrowException(env, IllegalArgument, "Can't get BufferCapacity.");
        return false;
    }
    bin = BinaryData(data, S(size));
    return true;
}

//*********************************************************************
// String handling
//*********************************************************************

namespace {

// This assumes that 'jchar' is an integral type with at least 16
// non-sign value bits, that is, an unsigned 16-bit integer, or any
// signed or unsigned integer with more than 16 bits.
struct JcharTraits {
    static jchar to_int_type(jchar c)  TIGHTDB_NOEXCEPT { return c; }
    static jchar to_char_type(jchar i) TIGHTDB_NOEXCEPT { return i; }
};

struct JStringCharsAccessor {
    JStringCharsAccessor(JNIEnv* e, jstring s):
        m_env(e), m_string(s), m_data(e->GetStringChars(s,0)), m_size(get_size(e,s)) {}
    ~JStringCharsAccessor()
    {
        m_env->ReleaseStringChars(m_string, m_data);
    }
    const jchar* data() const TIGHTDB_NOEXCEPT { return m_data; }
    size_t size() const TIGHTDB_NOEXCEPT { return m_size; }

private:
    JNIEnv* const m_env;
    const jstring m_string;
    const jchar* const m_data;
    const size_t m_size;

    static size_t get_size(JNIEnv* e, jstring s)
    {
        size_t size;
        if (int_cast_with_overflow_detect(e->GetStringLength(s), size))
            throw runtime_error("String size overflow");
        return size;
    }
};

} // anonymous namespace

string string_to_hex(const string& message, StringData& str) {
    ostringstream ret;

    const char *s = str.data();
    ret << message;
    for (string::size_type i = 0; i < str.size(); ++i)
        ret << " 0x" << std::hex << std::setfill('0') << std::setw(2) << (int)s[i];
    return ret.str();
}

string string_to_hex(const string& message, const jchar *str, size_t size) {
    ostringstream ret;

    ret << message;
    for (size_t i = 0; i < size; ++i)
        ret << " 0x" << std::hex << std::setfill('0') << std::setw(2) << (int)str[i];
    return ret.str();
}

jstring to_jstring(JNIEnv* env, StringData str)
{
    // Input is UTF-8 and output is UTF-16. Invalid UTF-8 input is
    // silently converted to Unicode replacement characters.

    // We use a small fixed size stack-allocated output buffer to avoid the cost
    // of dynamic allocation for short input strings. If this buffer turns out
    // to be too small, we proceed by calulating an estimate for the actual
    // required output buffer size, and then allocate the buffer dynamically.

    const size_t stack_buf_size = 48;
    jchar stack_buf[stack_buf_size];
    Buffer<jchar> dyn_buf;

    const char* in = str.data();
    const char* in_end = in + str.size();
    jchar* out = stack_buf;
    jchar* out_begin = out;
    jchar* out_end = out_begin + stack_buf_size;

    for (;;) {
        typedef Utf8x16<jchar, JcharTraits> Xcode;
        Xcode::to_utf16(in, in_end, out, out_end);
        bool end_of_input = in == in_end;
        if (end_of_input)
            break;
        bool bad_input = out != out_end;
        if (bad_input) {
            // Discard one or more invalid bytes from the input. We shall follow
            // the stardard way of doing this, namely by first discarding the
            // leading invalid byte, which must either be a sequence lead byte
            // (11xxxxxx) or a stray continuation byte (10xxxxxx), and then
            // discard any additional continuation bytes following leading
            // invalid byte.
            for (;;) {
                ++in;
                end_of_input = in == in_end;
                if (end_of_input)
                    break;
                bool next_byte_is_continuation = unsigned(*in) & 0xC0 == 0x80;
                if (!next_byte_is_continuation)
                    break;
            }
        }
        size_t used_size = out - out_begin; // What we already have
        size_t min_capacity = used_size;
        min_cpacity += 1; // Make space for a replacement character
        size_t in_2 = in; // Avoid clobbering `in`
        if (int_add_with_overflow_detect(min_capacity, Xcode::find_utf16_buf_size(in_2, in_end)))
            throw runtime_error("Buffer size overflow");
        bool copy_stack_buf = dyn_buf.size() == 0;
        size_t used_dyn_buf_size = copy_stack_buf ? 0 : used_size;
        dyn_buf.reserve(used_dyn_buf_size, min_capacity);
        out_begin = dyn_buf.data();
        out_end = dyn_buf.data() + dyn_buf.size();
        out = out_begin + used_size;
        if (copy_stack_buf)
            copy(stack_buf, stack_buf_out_end, out_begin);
        if (bad_input)
            *out++ = JcharTraits::to_char_type(0xFFFD); // Unicode replacement character
    }

    jsize out_size;
    if (int_cast_with_overflow_detect(out - out_begin, out_size))
        throw runtime_error("String size overflow");

    return env->NewString(out_begin, out_size);
}

JStringAccessor::JStringAccessor(JNIEnv* env, jstring str)
{
    // For efficiency, if the incoming UTF-16 string is sufficiently
    // small, we will choose an UTF-8 output buffer whose size (in
    // bytes) is simply 4 times the number of 16-bit elements in the
    // input. This is guaranteed to be enough. However, to avoid
    // excessive over allocation, this is not done for larger input
    // strings.

    JStringCharsAccessor chars(env, str);

    typedef Utf8x16<jchar, JcharTraits> Xcode;
    size_t max_project_size = 48;
    TIGHTDB_ASSERT(max_project_size <= numeric_limits<size_t>::max()/4);
    size_t buf_size;
    if (chars.size() <= max_project_size) {
        buf_size = chars.size() * 4;
    }
    else {
        const jchar* begin = chars.data();
        const jchar* end   = begin + chars.size();
        buf_size = Xcode::find_utf8_buf_size(begin, end);
    }
    m_data.reset(new char[buf_size]);  // throws
    {
        const jchar* in_begin = chars.data();
        const jchar* in_end   = in_begin + chars.size();
        char* out_begin = m_data.get();
        char* out_end   = m_data.get() + buf_size;
        if (!Xcode::to_utf8(in_begin, in_end, out_begin, out_end)) {
            throw runtime_error(string_to_hex("Failure when converting to UTF-8", chars.data(), chars.size()));
        }
        TIGHTDB_ASSERT(in_begin == in_end);
        m_size = out_begin - m_data.get();
    }
}
<commit_msg>Fix for: Lenient UTF-8 -> UTF-16 transcoding (insert replacement characters)<commit_after>/*
 * Copyright 2014 Realm 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 <algorithm>
#include <stdexcept>

#include <tightdb/util/assert.hpp>
#include <tightdb/util/utf8.hpp>
#include <tightdb/util/buffer.hpp>

#include "util.hpp"
#include "io_realm_internal_Util.h"

using namespace std;
using namespace tightdb;
using namespace tightdb::util;

void ThrowException(JNIEnv* env, ExceptionKind exception, std::string classStr, std::string itemStr)
{
    std::string message;
    jclass jExceptionClass = NULL;

    TR_ERR((env, "\njni: ThrowingException %d, %s, %s.\n", exception, classStr.c_str(), itemStr.c_str()));

    switch (exception) {
        case ClassNotFound:
            jExceptionClass = env->FindClass("java/lang/ClassNotFoundException");
            message = "Class '" + classStr + "' could not be located.";
            break;

        case NoSuchField:
            jExceptionClass = env->FindClass("java/lang/NoSuchFieldException");
            message = "Field '" + itemStr + "' could not be located in class io.realm." + classStr;
            break;

        case NoSuchMethod:
            jExceptionClass = env->FindClass("java/lang/NoSuchMethodException");
            message = "Method '" + itemStr + "' could not be located in class io.realm." + classStr;
            break;

        case IllegalArgument:
            jExceptionClass = env->FindClass("java/lang/IllegalArgumentException");
            message = "Illegal Argument: " + classStr;
            break;

        case TableInvalid:
            jExceptionClass = env->FindClass("java/lang/IllegalStateException");
            message = "Illegal State: " + classStr;
            break;

        case IOFailed:
            jExceptionClass = env->FindClass("io/realm/exceptions/RealmIOException");
            message = "Failed to open " + classStr + ". " + itemStr;
            break;

        case FileNotFound:
            jExceptionClass = env->FindClass("io/realm/exceptions/RealmIOException");
            message = "File not found: " + classStr + ".";
            break;

        case FileAccessError:
            jExceptionClass = env->FindClass("io/realm/exceptions/RealmIOException");
            message = "Failed to access: " + classStr + ". " + itemStr;
            break;

        case IndexOutOfBounds:
            jExceptionClass = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
            message = classStr;
            break;

        case UnsupportedOperation:
            jExceptionClass = env->FindClass("java/lang/UnsupportedOperationException");
            message = classStr;
            break;

        case OutOfMemory:
            jExceptionClass = env->FindClass("io/realm/internal/OutOfMemoryError");
            message = classStr + " " + itemStr;
            break;

        case Unspecified:
            jExceptionClass = env->FindClass("java/lang/RuntimeException");
            message = "Unspecified exception. " + classStr;
            break;

        case RuntimeError:
            jExceptionClass = env->FindClass("java/lang/RuntimeException");
            message = classStr;
            break;

        case RowInvalid:
            jExceptionClass = env->FindClass("java/lang/IllegalStateException");
            message = "Illegal State: " + classStr;
            break;
    }
    if (jExceptionClass != NULL)
        env->ThrowNew(jExceptionClass, message.c_str());
    else {
        TR_ERR((env, "\nERROR: Couldn't throw exception.\n"));
    }

    env->DeleteLocalRef(jExceptionClass);
}

jclass GetClass(JNIEnv* env, const char* classStr)
{
    jclass localRefClass = env->FindClass(classStr);
    if (localRefClass == NULL) {
        ThrowException(env, ClassNotFound, classStr);
        return NULL;
    }

    jclass myClass = reinterpret_cast<jclass>( env->NewGlobalRef(localRefClass) );
    env->DeleteLocalRef(localRefClass);
    return myClass;
}

void jprint(JNIEnv *env, char *txt)
{
#if 1
    static_cast<void>(env);
    fprintf(stderr, " -- JNI: %s", txt);  fflush(stderr);
#else
    static jclass myClass = GetClass(env, "io/realm/internal/Util");
    static jmethodID myMethod = env->GetStaticMethodID(myClass, "javaPrint", "(Ljava/lang/String;)V");
    if (myMethod)
        env->CallStaticVoidMethod(myClass, myMethod, to_jstring(env, txt));
    else
        ThrowException(env, NoSuchMethod, "Util", "javaPrint");
#endif
}

void jprintf(JNIEnv *env, const char *format, ...)
{
    va_list argptr;
    char buf[200];
    va_start(argptr, format);
    //vfprintf(stderr, format, argptr);
    vsnprintf(buf, 200, format, argptr);
    jprint(env, buf);
    va_end(argptr);
}

bool GetBinaryData(JNIEnv* env, jobject jByteBuffer, tightdb::BinaryData& bin)
{
    const char* data = static_cast<char*>(env->GetDirectBufferAddress(jByteBuffer));
    if (!data) {
        ThrowException(env, IllegalArgument, "ByteBuffer is invalid");
        return false;
    }
    jlong size = env->GetDirectBufferCapacity(jByteBuffer);
    if (size < 0) {
        ThrowException(env, IllegalArgument, "Can't get BufferCapacity.");
        return false;
    }
    bin = BinaryData(data, S(size));
    return true;
}

//*********************************************************************
// String handling
//*********************************************************************

namespace {

// This assumes that 'jchar' is an integral type with at least 16
// non-sign value bits, that is, an unsigned 16-bit integer, or any
// signed or unsigned integer with more than 16 bits.
struct JcharTraits {
    static jchar to_int_type(jchar c)  TIGHTDB_NOEXCEPT { return c; }
    static jchar to_char_type(jchar i) TIGHTDB_NOEXCEPT { return i; }
};

struct JStringCharsAccessor {
    JStringCharsAccessor(JNIEnv* e, jstring s):
        m_env(e), m_string(s), m_data(e->GetStringChars(s,0)), m_size(get_size(e,s)) {}
    ~JStringCharsAccessor()
    {
        m_env->ReleaseStringChars(m_string, m_data);
    }
    const jchar* data() const TIGHTDB_NOEXCEPT { return m_data; }
    size_t size() const TIGHTDB_NOEXCEPT { return m_size; }

private:
    JNIEnv* const m_env;
    const jstring m_string;
    const jchar* const m_data;
    const size_t m_size;

    static size_t get_size(JNIEnv* e, jstring s)
    {
        size_t size;
        if (int_cast_with_overflow_detect(e->GetStringLength(s), size))
            throw runtime_error("String size overflow");
        return size;
    }
};

} // anonymous namespace

string string_to_hex(const string& message, StringData& str) {
    ostringstream ret;

    const char *s = str.data();
    ret << message;
    for (string::size_type i = 0; i < str.size(); ++i)
        ret << " 0x" << std::hex << std::setfill('0') << std::setw(2) << (int)s[i];
    return ret.str();
}

string string_to_hex(const string& message, const jchar *str, size_t size) {
    ostringstream ret;

    ret << message;
    for (size_t i = 0; i < size; ++i)
        ret << " 0x" << std::hex << std::setfill('0') << std::setw(2) << (int)str[i];
    return ret.str();
}

jstring to_jstring(JNIEnv* env, StringData str)
{
    // Input is UTF-8 and output is UTF-16. Invalid UTF-8 input is
    // silently converted to Unicode replacement characters.

    // We use a small fixed size stack-allocated output buffer to avoid the cost
    // of dynamic allocation for short input strings. If this buffer turns out
    // to be too small, we proceed by calulating an estimate for the actual
    // required output buffer size, and then allocate the buffer dynamically.

    const size_t stack_buf_size = 48;
    jchar stack_buf[stack_buf_size];
    Buffer<jchar> dyn_buf;

    const char* in = str.data();
    const char* in_end = in + str.size();
    jchar* out = stack_buf;
    jchar* out_begin = out;
    jchar* out_end = out_begin + stack_buf_size;

    for (;;) {
        typedef Utf8x16<jchar, JcharTraits> Xcode;
        Xcode::to_utf16(in, in_end, out, out_end);
        bool end_of_input = in == in_end;
        if (end_of_input)
            break;
        bool bad_input = out != out_end;
        if (bad_input) {
            // Discard one or more invalid bytes from the input. We shall follow
            // the stardard way of doing this, namely by first discarding the
            // leading invalid byte, which must either be a sequence lead byte
            // (11xxxxxx) or a stray continuation byte (10xxxxxx), and then
            // discard any additional continuation bytes following leading
            // invalid byte.
            for (;;) {
                ++in;
                end_of_input = in == in_end;
                if (end_of_input)
                    break;
                bool next_byte_is_continuation = unsigned(*in) & 0xC0 == 0x80;
                if (!next_byte_is_continuation)
                    break;
            }
        }
        size_t used_size = out - out_begin; // What we already have
        size_t min_capacity = used_size;
        min_cpacity += 1; // Make space for a replacement character
        size_t in_2 = in; // Avoid clobbering `in`
        if (int_add_with_overflow_detect(min_capacity, Xcode::find_utf16_buf_size(in_2, in_end)))
            throw runtime_error("Buffer size overflow");
        bool copy_stack_buf = dyn_buf.size() == 0;
        size_t used_dyn_buf_size = copy_stack_buf ? 0 : used_size;
        dyn_buf.reserve(used_dyn_buf_size, min_capacity);
        if (copy_stack_buf)
            copy(out_begin, out, dyn_buf.data());
        out_begin = dyn_buf.data();
        out_end = dyn_buf.data() + dyn_buf.size();
        out = out_begin + used_size;
        if (bad_input)
            *out++ = JcharTraits::to_char_type(0xFFFD); // Unicode replacement character
    }

    jsize out_size;
    if (int_cast_with_overflow_detect(out - out_begin, out_size))
        throw runtime_error("String size overflow");

    return env->NewString(out_begin, out_size);
}

JStringAccessor::JStringAccessor(JNIEnv* env, jstring str)
{
    // For efficiency, if the incoming UTF-16 string is sufficiently
    // small, we will choose an UTF-8 output buffer whose size (in
    // bytes) is simply 4 times the number of 16-bit elements in the
    // input. This is guaranteed to be enough. However, to avoid
    // excessive over allocation, this is not done for larger input
    // strings.

    JStringCharsAccessor chars(env, str);

    typedef Utf8x16<jchar, JcharTraits> Xcode;
    size_t max_project_size = 48;
    TIGHTDB_ASSERT(max_project_size <= numeric_limits<size_t>::max()/4);
    size_t buf_size;
    if (chars.size() <= max_project_size) {
        buf_size = chars.size() * 4;
    }
    else {
        const jchar* begin = chars.data();
        const jchar* end   = begin + chars.size();
        buf_size = Xcode::find_utf8_buf_size(begin, end);
    }
    m_data.reset(new char[buf_size]);  // throws
    {
        const jchar* in_begin = chars.data();
        const jchar* in_end   = in_begin + chars.size();
        char* out_begin = m_data.get();
        char* out_end   = m_data.get() + buf_size;
        if (!Xcode::to_utf8(in_begin, in_end, out_begin, out_end)) {
            throw runtime_error(string_to_hex("Failure when converting to UTF-8", chars.data(), chars.size()));
        }
        TIGHTDB_ASSERT(in_begin == in_end);
        m_size = out_begin - m_data.get();
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix trivial bug introduced in #683<commit_after><|endoftext|>