<commit_before>#include <iostream>
#include <curl/curl.h>
#include <string>
#include <sstream>
#include <fstream>
#include <limits>

#include "rapidjson/document.h"
#include "geojson.h"
#include "tileData.h"
#include "earcut.hpp"
#include "objexport.h"
#include "aobaker.h"

namespace mapbox {
namespace util {
template <>
struct nth<0, Point> {
    inline static float get(const Point &t) { return t.x; };
};

template <>
struct nth<1, Point> {
    inline static float get(const Point &t) { return t.y; };
};
}}

struct PolygonVertex {
    glm::vec3 position;
    glm::vec3 normal;
};

struct PolygonMesh {
    std::vector<unsigned int> indices;
    std::vector<PolygonVertex> vertices;
};

static size_t write_data(void *_ptr, size_t _size, size_t _nmemb, void *_stream) {
    ((std::stringstream*) _stream)->write(reinterpret_cast<char *>(_ptr), _size * _nmemb);
    return _size * _nmemb;
}

std::unique_ptr<TileData> downloadTile(const std::string& _url, const Tile& _tile) {
    curl_global_init(CURL_GLOBAL_DEFAULT);

    bool success = true;

    CURL* curlHandle = curl_easy_init();

    std::stringstream out;

    // set up curl to perform fetch
    curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, &out);
    curl_easy_setopt(curlHandle, CURLOPT_URL, _url.c_str());
    curl_easy_setopt(curlHandle, CURLOPT_HEADER, 0L);
    curl_easy_setopt(curlHandle, CURLOPT_VERBOSE, 0L);
    curl_easy_setopt(curlHandle, CURLOPT_ACCEPT_ENCODING, "gzip");
    curl_easy_setopt(curlHandle, CURLOPT_NOSIGNAL, 1L);

    printf("Fetching URL with curl: %s\n", _url.c_str());

    CURLcode result = curl_easy_perform(curlHandle);

    if (result != CURLE_OK) {
        printf("curl_easy_perform failed: %s\n", curl_easy_strerror(result));
        success = false;
    } else {
        printf("Fetched tile: %s\n", _url.c_str());

        // parse written data into a JSON object
        rapidjson::Document doc;
        doc.Parse(out.str().c_str());

        if (doc.HasParseError()) {
            printf("Error parsing tile\n");
            return nullptr;
        }

        std::unique_ptr<TileData> data = std::unique_ptr<TileData>(new TileData());
        for (auto layer = doc.MemberBegin(); layer != doc.MemberEnd(); ++layer) {
            data->layers.emplace_back(std::string(layer->name.GetString()));
            GeoJson::extractLayer(layer->value, data->layers.back(), _tile);
        }

        return std::move(data);
    }

    return nullptr;
}

void buildPolygonExtrusion(const Polygon& _polygon,
    double _minHeight,
    double _height,
    std::vector<PolygonVertex>& _vertices,
    std::vector<unsigned int>& _indices)
{
    int vertexDataOffset = _vertices.size();
    glm::vec3 upVector(0.0f, 0.0f, 1.0f);
    glm::vec3 normalVector;

    for (auto& line : _polygon) {
        size_t lineSize = line.size();
        for (size_t i = 0; i < lineSize - 1; i++) {
            glm::vec3 a(line[i]);
            glm::vec3 b(line[i+1]);

            if (a == b) { continue; }

            normalVector = glm::cross(upVector, b - a);
            normalVector = glm::normalize(normalVector);

            a.z = _height;
            _vertices.push_back({a, normalVector});
            b.z = _height;
            _vertices.push_back({b, normalVector});
            a.z = _minHeight;
            _vertices.push_back({a, normalVector});
            b.z = _minHeight;
            _vertices.push_back({b, normalVector});

            _indices.push_back(vertexDataOffset);
            _indices.push_back(vertexDataOffset + 1);
            _indices.push_back(vertexDataOffset + 2);
            _indices.push_back(vertexDataOffset + 1);
            _indices.push_back(vertexDataOffset + 3);
            _indices.push_back(vertexDataOffset + 2);

            vertexDataOffset += 4;
        }
    }
}

void buildPolygon(const Polygon& _polygon, double _height, std::vector<PolygonVertex>& _vertices,
    std::vector<unsigned int>& _indices)
{
    mapbox::Earcut<float, unsigned int> earcut;

    earcut(_polygon);

    unsigned int vertexDataOffset = _vertices.size();

    if (earcut.indices.size() == 0) return;

    if (vertexDataOffset == 0) {
        _indices = std::move(earcut.indices);
    } else {
        _indices.reserve(_indices.size() + earcut.indices.size());
        for (auto i : earcut.indices) {
            _indices.push_back(vertexDataOffset + i);
        }
    }

    static glm::vec3 normal(0.0, 0.0, 1.0);

    for (auto& p : earcut.vertices) {
        glm::vec3 coord(p[0], p[1], _height);
        _vertices.push_back({coord, normal});
    }
}

bool saveOBJ(std::string _outputOBJ,
    bool _splitMeshes,
    std::vector<PolygonMesh>& _meshes,
    float _offsetX,
    float _offsetY,
    bool _append,
    Tile _tile)
{

    /// Cleanup mesh from degenerate points
    {
        for (auto& mesh : _meshes) {
            if (mesh.indices.size() == 0) continue;

            int i = 0;
            for (auto it = mesh.indices.begin(); it < mesh.indices.end() - 2;) {
                glm::vec3 p0 = mesh.vertices[mesh.indices[i+0]].position;
                glm::vec3 p1 = mesh.vertices[mesh.indices[i+1]].position;
                glm::vec3 p2 = mesh.vertices[mesh.indices[i+2]].position;

                if (p0 == p1 || p0 == p2) {
                    for (int j = 0; j < 3; ++j) {
                        it = mesh.indices.erase(it);
                    }
                } else {
                    it += 3;
                }

                i += 3;
            }
        }
    }

    size_t maxindex = 0;

    /// Find max index from previously existing wavefront vertices
    {
        std::ifstream filein(_outputOBJ.c_str(), std::ios::in);
        std::string token;

        if (filein.good() && _append) {
            // TODO: optimize this
            while (!filein.eof()) {
                filein >> token;
                if (token == "f") {
                    std::string faceLine;
                    getline(filein, faceLine);

                    for (unsigned int i = 0; i < faceLine.length(); ++i) {
                        if (faceLine[i] == '/') {
                            faceLine[i] = ' ';
                        }
                    }

                    std::stringstream ss(faceLine);
                    std::string faceToken;

                    for (int i = 0; i < 6; ++i) {
                        ss >> faceToken;
                        if (faceToken.find_first_not_of("\t\n ") != std::string::npos) {
                            size_t index = atoi(faceToken.c_str());
                            maxindex = index > maxindex ? index : maxindex;
                        }
                    }
                }
            }

            filein.close();
        }
    }

    /// Save obj file
    {
        std::ofstream file;
        if (_append) {
            file = std::ofstream(_outputOBJ, std::ios_base::app);
        } else {
            file = std::ofstream(_outputOBJ);
        }

        if (file.is_open()) {
            file << "# exported with vectiler: https://github.com/karimnaaji/vectiler" << "\n";
            file << "\n";

            int indexOffset = maxindex;

            if (_splitMeshes) {
                int meshCnt = 0;

                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }
                    file << "# tile " << _tile.x << " " << _tile.y << " " << _tile.z << "\n";

                    file << "o mesh" << meshCnt++ << "\n";
                    for (auto vertex : mesh.vertices) {
                        file << "v " << vertex.position.x + _offsetX << " "
                             << vertex.position.y + _offsetY << " "
                             << vertex.position.z << "\n";
                    }
                    for (auto vertex : mesh.vertices) {
                        file << "vn " << vertex.normal.x << " "
                             << vertex.normal.y << " "
                             << vertex.normal.z << "\n";
                    }
                    for (int i = 0; i < mesh.indices.size(); i += 3) {
                        file << "f " << mesh.indices[i] + indexOffset + 1 << "//"
                             << mesh.indices[i] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+1] + indexOffset + 1 << "//"
                             << mesh.indices[i+1] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+2] + indexOffset + 1 << "//"
                             << mesh.indices[i+2] + indexOffset + 1 << "\n";
                    }
                    file << "\n";
                    indexOffset += mesh.vertices.size();
                }
            } else {
                file << "o tile_" << _tile.x << "_" << _tile.y << "_" << _tile.z << "\n";

                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }

                    for (auto vertex : mesh.vertices) {
                        file << "v " << vertex.position.x + _offsetX << " "
                             << vertex.position.y + _offsetY << " "
                             << vertex.position.z << "\n";
                    }
                }
                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }

                    for (auto vertex : mesh.vertices) {
                        file << "vn " << vertex.normal.x << " "
                             << vertex.normal.y << " "
                             << vertex.normal.z << "\n";
                    }
                }
                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }

                    for (int i = 0; i < mesh.indices.size(); i += 3) {
                        file << "f " << mesh.indices[i] + indexOffset + 1 << "//"
                             << mesh.indices[i] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+1] + indexOffset + 1 << "//"
                             << mesh.indices[i+1] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+2] + indexOffset + 1 << "//"
                             << mesh.indices[i+2] + indexOffset + 1 << "\n";
                    }
                    indexOffset += mesh.vertices.size();
                }
            }

            file.close();
            printf("Save %s\n", _outputOBJ.c_str());
            return true;
        } else {
            printf("Can't open file %s", _outputOBJ.c_str());
        }
    }
    return false;
}

int objexport(const char* _filename,
    int _tileX,
    int _tileY,
    int _tileZ,
    float _offsetX,
    float _offsetY,
    bool _splitMeshes,
    int _sizehint,
    int _nsamples,
    bool _bakeAO,
    bool _append)
{
    std::string apiKey = "vector-tiles-qVaBcRA";
    std::string url = "http://vector.mapzen.com/osm/all/"
        + std::to_string(_tileZ) + "/"
        + std::to_string(_tileX) + "/"
        + std::to_string(_tileY) + ".json?api_key=" + apiKey;

    Tile tile = {_tileX, _tileY, _tileZ};
    auto data = downloadTile(url, tile);

    if (!data) {
        printf("Failed to download tile data\n");
        return EXIT_FAILURE;
    }

    glm::dvec4 bounds = tileBounds(tile, 256.0);
    double scale = 0.5 * glm::abs(bounds.x - bounds.z);
    double invScale = 1.0 / scale;

    const static std::string key_height("height");
    const static std::string key_min_height("min_height");

    std::vector<PolygonMesh> meshes;
    for (auto layer : data->layers) {
        // TODO: give layer as parameter, to filter
        for (auto feature : layer.features) {
            auto itHeight = feature.props.numericProps.find(key_height);
            auto itMinHeight = feature.props.numericProps.find(key_min_height);
            double height = 0.0;
            double minHeight = 0.0;
            if (itHeight != feature.props.numericProps.end()) {
                height = itHeight->second * invScale;
            }
            if (itMinHeight != feature.props.numericProps.end()) {
                minHeight = itMinHeight->second * invScale;
            }
            PolygonMesh mesh;
            for (auto polygon : feature.polygons) {
                if (minHeight != height) {
                    buildPolygonExtrusion(polygon, minHeight, height,
                        mesh.vertices, mesh.indices);
                }
                buildPolygon(polygon, height, mesh.vertices, mesh.indices);
            }
            meshes.push_back(mesh);
        }
    }

    std::string outFile;

    if (_filename) {
        outFile = std::string(_filename);
    } else {
        outFile = std::to_string(_tileX) + "." + std::to_string(_tileY) + "." + std::to_string(_tileZ);
    }

    std::string outputOBJ = outFile + ".obj";

    if (!saveOBJ(outputOBJ, _splitMeshes, meshes, _offsetX, _offsetY, _append, tile)) {
        return EXIT_FAILURE;
    }

    if (_bakeAO) {
        return aobaker_bake(outputOBJ.c_str(), (outFile + "-ao.obj").c_str(),
                (outFile + ".png").c_str(), _sizehint, _nsamples, false, false, 1.0);
    }

    return EXIT_SUCCESS;
}
<commit_msg>Reduce reallocs<commit_after>#include <iostream>
#include <curl/curl.h>
#include <string>
#include <sstream>
#include <fstream>
#include <limits>

#include "rapidjson/document.h"
#include "geojson.h"
#include "tileData.h"
#include "earcut.hpp"
#include "objexport.h"
#include "aobaker.h"

namespace mapbox {
namespace util {
template <>
struct nth<0, Point> {
    inline static float get(const Point &t) { return t.x; };
};

template <>
struct nth<1, Point> {
    inline static float get(const Point &t) { return t.y; };
};
}}

struct PolygonVertex {
    glm::vec3 position;
    glm::vec3 normal;
};

struct PolygonMesh {
    std::vector<unsigned int> indices;
    std::vector<PolygonVertex> vertices;
};

static size_t write_data(void *_ptr, size_t _size, size_t _nmemb, void *_stream) {
    ((std::stringstream*) _stream)->write(reinterpret_cast<char *>(_ptr), _size * _nmemb);
    return _size * _nmemb;
}

std::unique_ptr<TileData> downloadTile(const std::string& _url, const Tile& _tile) {
    curl_global_init(CURL_GLOBAL_DEFAULT);

    bool success = true;

    CURL* curlHandle = curl_easy_init();

    std::stringstream out;

    // set up curl to perform fetch
    curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, &out);
    curl_easy_setopt(curlHandle, CURLOPT_URL, _url.c_str());
    curl_easy_setopt(curlHandle, CURLOPT_HEADER, 0L);
    curl_easy_setopt(curlHandle, CURLOPT_VERBOSE, 0L);
    curl_easy_setopt(curlHandle, CURLOPT_ACCEPT_ENCODING, "gzip");
    curl_easy_setopt(curlHandle, CURLOPT_NOSIGNAL, 1L);

    printf("Fetching URL with curl: %s\n", _url.c_str());

    CURLcode result = curl_easy_perform(curlHandle);

    if (result != CURLE_OK) {
        printf("curl_easy_perform failed: %s\n", curl_easy_strerror(result));
        success = false;
    } else {
        printf("Fetched tile: %s\n", _url.c_str());

        // parse written data into a JSON object
        rapidjson::Document doc;
        doc.Parse(out.str().c_str());

        if (doc.HasParseError()) {
            printf("Error parsing tile\n");
            return nullptr;
        }

        std::unique_ptr<TileData> data = std::unique_ptr<TileData>(new TileData());
        for (auto layer = doc.MemberBegin(); layer != doc.MemberEnd(); ++layer) {
            data->layers.emplace_back(std::string(layer->name.GetString()));
            GeoJson::extractLayer(layer->value, data->layers.back(), _tile);
        }

        return std::move(data);
    }

    return nullptr;
}

void buildPolygonExtrusion(const Polygon& _polygon,
    double _minHeight,
    double _height,
    std::vector<PolygonVertex>& _vertices,
    std::vector<unsigned int>& _indices)
{
    int vertexDataOffset = _vertices.size();
    glm::vec3 upVector(0.0f, 0.0f, 1.0f);
    glm::vec3 normalVector;

    for (auto& line : _polygon) {
        size_t lineSize = line.size();

        _vertices.reserve(_vertices.size() + lineSize * 4);
        _indices.reserve(_indices.size() + lineSize * 6);

        for (size_t i = 0; i < lineSize - 1; i++) {
            glm::vec3 a(line[i]);
            glm::vec3 b(line[i+1]);

            if (a == b) { continue; }

            normalVector = glm::cross(upVector, b - a);
            normalVector = glm::normalize(normalVector);

            a.z = _height;
            _vertices.push_back({a, normalVector});
            b.z = _height;
            _vertices.push_back({b, normalVector});
            a.z = _minHeight;
            _vertices.push_back({a, normalVector});
            b.z = _minHeight;
            _vertices.push_back({b, normalVector});

            _indices.push_back(vertexDataOffset);
            _indices.push_back(vertexDataOffset + 1);
            _indices.push_back(vertexDataOffset + 2);
            _indices.push_back(vertexDataOffset + 1);
            _indices.push_back(vertexDataOffset + 3);
            _indices.push_back(vertexDataOffset + 2);

            vertexDataOffset += 4;
        }
    }
}

void buildPolygon(const Polygon& _polygon,
    double _height,
    std::vector<PolygonVertex>& _vertices,
    std::vector<unsigned int>& _indices)
{
    mapbox::Earcut<float, unsigned int> earcut;

    earcut(_polygon);

    unsigned int vertexDataOffset = _vertices.size();

    if (earcut.indices.size() == 0) return;

    if (vertexDataOffset == 0) {
        _indices = std::move(earcut.indices);
    } else {
        _indices.reserve(_indices.size() + earcut.indices.size());
        for (auto i : earcut.indices) {
            _indices.push_back(vertexDataOffset + i);
        }
    }

    static glm::vec3 normal(0.0, 0.0, 1.0);

    _vertices.reserve(_vertices.size() + earcut.vertices.size());

    for (auto& p : earcut.vertices) {
        glm::vec3 coord(p[0], p[1], _height);
        _vertices.push_back({coord, normal});
    }
}

bool saveOBJ(std::string _outputOBJ,
    bool _splitMeshes,
    std::vector<PolygonMesh>& _meshes,
    float _offsetX,
    float _offsetY,
    bool _append,
    Tile _tile)
{

    /// Cleanup mesh from degenerate points
    {
        for (auto& mesh : _meshes) {
            if (mesh.indices.size() == 0) continue;

            int i = 0;
            for (auto it = mesh.indices.begin(); it < mesh.indices.end() - 2;) {
                glm::vec3 p0 = mesh.vertices[mesh.indices[i+0]].position;
                glm::vec3 p1 = mesh.vertices[mesh.indices[i+1]].position;
                glm::vec3 p2 = mesh.vertices[mesh.indices[i+2]].position;

                if (p0 == p1 || p0 == p2) {
                    for (int j = 0; j < 3; ++j) {
                        it = mesh.indices.erase(it);
                    }
                } else {
                    it += 3;
                }

                i += 3;
            }
        }
    }

    size_t maxindex = 0;

    /// Find max index from previously existing wavefront vertices
    {
        std::ifstream filein(_outputOBJ.c_str(), std::ios::in);
        std::string token;

        if (filein.good() && _append) {
            // TODO: optimize this
            while (!filein.eof()) {
                filein >> token;
                if (token == "f") {
                    std::string faceLine;
                    getline(filein, faceLine);

                    for (unsigned int i = 0; i < faceLine.length(); ++i) {
                        if (faceLine[i] == '/') {
                            faceLine[i] = ' ';
                        }
                    }

                    std::stringstream ss(faceLine);
                    std::string faceToken;

                    for (int i = 0; i < 6; ++i) {
                        ss >> faceToken;
                        if (faceToken.find_first_not_of("\t\n ") != std::string::npos) {
                            size_t index = atoi(faceToken.c_str());
                            maxindex = index > maxindex ? index : maxindex;
                        }
                    }
                }
            }

            filein.close();
        }
    }

    /// Save obj file
    {
        std::ofstream file;
        if (_append) {
            file = std::ofstream(_outputOBJ, std::ios_base::app);
        } else {
            file = std::ofstream(_outputOBJ);
        }

        if (file.is_open()) {
            file << "# exported with vectiler: https://github.com/karimnaaji/vectiler" << "\n";
            file << "\n";

            int indexOffset = maxindex;

            if (_splitMeshes) {
                int meshCnt = 0;

                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }
                    file << "# tile " << _tile.x << " " << _tile.y << " " << _tile.z << "\n";

                    file << "o mesh" << meshCnt++ << "\n";
                    for (auto vertex : mesh.vertices) {
                        file << "v " << vertex.position.x + _offsetX << " "
                             << vertex.position.y + _offsetY << " "
                             << vertex.position.z << "\n";
                    }
                    for (auto vertex : mesh.vertices) {
                        file << "vn " << vertex.normal.x << " "
                             << vertex.normal.y << " "
                             << vertex.normal.z << "\n";
                    }
                    for (int i = 0; i < mesh.indices.size(); i += 3) {
                        file << "f " << mesh.indices[i] + indexOffset + 1 << "//"
                             << mesh.indices[i] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+1] + indexOffset + 1 << "//"
                             << mesh.indices[i+1] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+2] + indexOffset + 1 << "//"
                             << mesh.indices[i+2] + indexOffset + 1 << "\n";
                    }
                    file << "\n";
                    indexOffset += mesh.vertices.size();
                }
            } else {
                file << "o tile_" << _tile.x << "_" << _tile.y << "_" << _tile.z << "\n";

                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }

                    for (auto vertex : mesh.vertices) {
                        file << "v " << vertex.position.x + _offsetX << " "
                             << vertex.position.y + _offsetY << " "
                             << vertex.position.z << "\n";
                    }
                }
                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }

                    for (auto vertex : mesh.vertices) {
                        file << "vn " << vertex.normal.x << " "
                             << vertex.normal.y << " "
                             << vertex.normal.z << "\n";
                    }
                }
                for (const PolygonMesh& mesh : _meshes) {
                    if (mesh.vertices.size() == 0) { continue; }

                    for (int i = 0; i < mesh.indices.size(); i += 3) {
                        file << "f " << mesh.indices[i] + indexOffset + 1 << "//"
                             << mesh.indices[i] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+1] + indexOffset + 1 << "//"
                             << mesh.indices[i+1] + indexOffset + 1;
                        file << " ";
                        file << mesh.indices[i+2] + indexOffset + 1 << "//"
                             << mesh.indices[i+2] + indexOffset + 1 << "\n";
                    }
                    indexOffset += mesh.vertices.size();
                }
            }

            file.close();
            printf("Save %s\n", _outputOBJ.c_str());
            return true;
        } else {
            printf("Can't open file %s", _outputOBJ.c_str());
        }
    }
    return false;
}

int objexport(const char* _filename,
    int _tileX,
    int _tileY,
    int _tileZ,
    float _offsetX,
    float _offsetY,
    bool _splitMeshes,
    int _sizehint,
    int _nsamples,
    bool _bakeAO,
    bool _append)
{
    std::string apiKey = "vector-tiles-qVaBcRA";
    std::string url = "http://vector.mapzen.com/osm/all/"
        + std::to_string(_tileZ) + "/"
        + std::to_string(_tileX) + "/"
        + std::to_string(_tileY) + ".json?api_key=" + apiKey;

    Tile tile = {_tileX, _tileY, _tileZ};
    auto data = downloadTile(url, tile);

    if (!data) {
        printf("Failed to download tile data\n");
        return EXIT_FAILURE;
    }

    glm::dvec4 bounds = tileBounds(tile, 256.0);
    double scale = 0.5 * glm::abs(bounds.x - bounds.z);
    double invScale = 1.0 / scale;

    const static std::string keyHeight("height");
    const static std::string keyMinHeight("min_height");

    std::vector<PolygonMesh> meshes;
    for (auto layer : data->layers) {
        // TODO: give layer as parameter, to filter
        for (auto feature : layer.features) {
            auto itHeight = feature.props.numericProps.find(keyHeight);
            auto itMinHeight = feature.props.numericProps.find(keyMinHeight);
            double height = 0.0;
            double minHeight = 0.0;
            if (itHeight != feature.props.numericProps.end()) {
                height = itHeight->second * invScale;
            }
            if (itMinHeight != feature.props.numericProps.end()) {
                minHeight = itMinHeight->second * invScale;
            }
            PolygonMesh mesh;
            for (auto polygon : feature.polygons) {
                if (minHeight != height) {
                    buildPolygonExtrusion(polygon, minHeight, height,
                        mesh.vertices, mesh.indices);
                }
                buildPolygon(polygon, height, mesh.vertices, mesh.indices);
            }
            meshes.push_back(mesh);
        }
    }

    std::string outFile;

    if (_filename) {
        outFile = std::string(_filename);
    } else {
        outFile = std::to_string(_tileX) + "." + std::to_string(_tileY) + "." + std::to_string(_tileZ);
    }

    std::string outputOBJ = outFile + ".obj";

    if (!saveOBJ(outputOBJ, _splitMeshes, meshes, _offsetX, _offsetY, _append, tile)) {
        return EXIT_FAILURE;
    }

    if (_bakeAO) {
        return aobaker_bake(outputOBJ.c_str(), (outFile + "-ao.obj").c_str(),
                (outFile + ".png").c_str(), _sizehint, _nsamples, false, false, 1.0);
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
/// \file  pcapcut.cpp
//------------------------------------------------------------------------------
/// \brief Utility for cutting a part of a large pcap file
/// \see
///      Alternative implementation using pcap.h
//------------------------------------------------------------------------------
// Copyright (c) 2016 Serge Aleynikov <saleyn@gmail.com>
// Created: 2016-11-28
//------------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <signal.h>
#include <utxx/pcap.hpp>
#include <utxx/string.hpp>
#include <utxx/path.hpp>
#include <utxx/get_option.hpp>
#include <utxx/buffer.hpp>
#include <utxx/version.hpp>

using namespace std;

//------------------------------------------------------------------------------
void usage(std::string const& err="")
{
    auto prog = utxx::path::basename(
        utxx::path::program::name().c_str(),
        utxx::path::program::name().c_str() + utxx::path::program::name().size()
    );

    if (!err.empty())
        cerr << "Invalid option: " << err << "\n\n";
    else {
        cerr << prog <<
        " - Tool for extracting packets from a pcap file\n"
        "Copyright (c) 2016 Serge Aleynikov\n"  <<
        VERSION() << "\n\n"                     <<
        "Usage: " << prog                       <<
        "[-V] [-h] -f InputFile -s StartPktNum -e EndPktNum [-n NumPkts] [-c|--count]"
                    " -o|-O OutputFile [-h]\n\n"
        "   -V|--version            - Version\n"
        "   -h|--help               - Help screen\n"
        "   -f InputFile            - Input file name\n"
        "   -o OutputFile           - Ouput file name (don't overwrite if exists)\n"
        "   -O OutputFile           - Ouput file name (overwrite if exists)\n"
        "   -s|--start StartPktNum  - Starting packet number (counting from 1)\n"
        "   -e|--end   EndPktNum    - Ending packet number (must be >= StartPktNum)\n"
        "   -n|--num   TotNumPkts   - Number of packets to save\n"
        "   -r|--raw                - Output raw packet payload only without pcap format\n"
        "   -c|--count              - Count number of packets in the file\n"
        "   -v                      - Verbose\n\n";
    }

    exit(1);
}

//------------------------------------------------------------------------------
void unhandled_exception() {
  auto p = current_exception();
  try    { rethrow_exception(p); }
  catch  ( exception& e ) { cerr << e.what() << endl; }
  catch  ( ... )          { cerr << "Unknown exception" << endl; }
  exit(1);
}

//------------------------------------------------------------------------------
//  MAIN
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    string in_file;
    string out_file;
    size_t pk_start  = 1, pk_end = 0, pk_cnt = 0;
    bool   overwrite = false;
    bool   raw_mode  = false;
    bool   count     = false;
    bool   verbose   = false;

    set_terminate (&unhandled_exception);

    utxx::opts_parser opts(argc, argv);

    while (opts.next()) {
        if (opts.match("-f", "",        &in_file))  continue;
        if (opts.match("-o", "",        &out_file)) continue;
        if (opts.match("-O", "",        &out_file)){overwrite=true; continue;}
        if (opts.match("-r", "--raw",   &raw_mode)) continue;
        if (opts.match("-s", "--start", &pk_start)) continue;
        if (opts.match("-e", "--end",   &pk_end))   continue;
        if (opts.match("-n", "--num",   &pk_cnt))   continue;
        if (opts.match("-c", "--count", &count))    continue;
        if (opts.match("-v", "",        &verbose))  continue;
        if (opts.match("-V", "--version")) throw std::runtime_error(VERSION());
        if (opts.is_help())                         usage();

        usage(opts());
    }

    if (pk_end > 0 && pk_cnt > 0)
        throw std::runtime_error("Cannot specify both -n and -e options!");
    else if (!pk_end && !pk_cnt && !count)
        throw std::runtime_error("Must specify either -n or -e option!");
    else if (!pk_start && !count)
        throw std::runtime_error("PktStartNumber (-s) must be greater than 0!");
    else if (pk_end && pk_end < pk_start)
        throw std::runtime_error
             ("Ending packet number (-e) must not be less than starting packet number (-s)!");
    else if (in_file.empty() || (!count && out_file.empty()))
        throw std::runtime_error("Must specify -f and -o options!");
    else if (!count && utxx::path::file_exists(out_file)) {
        if (!overwrite)
            throw std::runtime_error("Found existing output file: " + out_file);
        if (!utxx::path::file_unlink(out_file))
            throw std::runtime_error("Error deleting file " + out_file +
                                     ": " + strerror(errno));
    }

    if (pk_cnt) {
        pk_end = pk_start + pk_cnt - 1;
        pk_cnt = 0;
    }

    utxx::pcap fin;
    if (fin.open_read(in_file) < 0)
        throw std::runtime_error("Error opening " + in_file + ": " + strerror(errno));
    else if (fin.read_file_header() < 0)
        throw std::runtime_error("File " + in_file + " is not in PCAP format!");

    int n = 0;
    utxx::pcap fout(fin.big_endian(), fin.nsec_time());

    if (!count) {
        n = raw_mode ? fout.open(out_file.c_str(), "wb")
                    : fout.open_write(out_file, false, fin.get_link_type());
        if (n < 0)
            throw std::runtime_error("Error creating file " + out_file + ": " + strerror(errno));
    }

    utxx::basic_io_buffer<(1024*1024)> buf;

    while ((n = fin.read(buf.wr_ptr(), buf.capacity())) > 0) {
        buf.commit(n);
        if (verbose)
            cerr << "Read "    << n   << " bytes from source file (offset="
                 << fin.tell() << ')' << endl;

        while (buf.size() > sizeof(utxx::pcap::packet_header)) {
            const char*       header;
            const char*       begin  = header = buf.rd_ptr();
            int               frame_sz, sz;
            utxx::pcap::proto proto;

            // sz - total size of payload including frame_sz
            std::tie(frame_sz, sz, proto) = fin.read_packet_hdr_and_frame(begin, n);

            if (frame_sz < 0 || int(buf.size()) < sz) { // Not enough data in the buffer
                if (verbose && frame_sz < 0)
                    cerr << "Pkt#" << (pk_cnt+1) << ": Cannot read frame size of packet\n";
                buf.reserve(sz);
                break;
            }

            if (verbose)
                cerr << "Pkt#"     << (pk_cnt+1) << " FrameSz=" << setw(2)    << frame_sz
                     << " Bytes="  << sz         << " BufSz="   << buf.size()
                     << endl;

            if (++pk_cnt >= pk_start && !count) {
                if (pk_cnt > pk_end)
                    goto DONE;

                // Write to the output file
                if (!raw_mode) {
                    fout.write_packet_header(fin.packet());
                    buf.read(sizeof(utxx::pcap::packet_header));
                    sz    -= sizeof(utxx::pcap::packet_header);
                } else {
                    buf.read(frame_sz);
                    sz    -= frame_sz;
                }
                if (fout.write(buf.rd_ptr(), sz) < 0)
                    throw std::runtime_error(string("Error writing to file: ") + strerror(errno));
            }

            buf.read(sz);
        }

        buf.crunch();
    }

  DONE:
    fout.close();
    fin.close();

    if (count)
        cout << pk_cnt << " packets\n";

    return 0;
}<commit_msg>Add info<commit_after>//------------------------------------------------------------------------------
/// \file  pcapcut.cpp
//------------------------------------------------------------------------------
/// \brief Utility for cutting a part of a large pcap file
/// \see
///      Alternative implementation using pcap.h
//------------------------------------------------------------------------------
// Copyright (c) 2016 Serge Aleynikov <saleyn@gmail.com>
// Created: 2016-11-28
//------------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <signal.h>
#include <utxx/pcap.hpp>
#include <utxx/string.hpp>
#include <utxx/path.hpp>
#include <utxx/get_option.hpp>
#include <utxx/buffer.hpp>
#include <utxx/version.hpp>

using namespace std;

//------------------------------------------------------------------------------
void usage(std::string const& err="")
{
    auto prog = utxx::path::basename(
        utxx::path::program::name().c_str(),
        utxx::path::program::name().c_str() + utxx::path::program::name().size()
    );

    if (!err.empty())
        cerr << "Invalid option: " << err << "\n\n";
    else {
        cerr << prog <<
        " - Tool for extracting packets from a pcap file\n"
        "Copyright (c) 2016 Serge Aleynikov\n"  <<
        VERSION() << "\n\n"                     <<
        "Usage: " << prog                       <<
        "[-V] [-h] -f InputFile -s StartPktNum -e EndPktNum [-n NumPkts] [-c|--count]"
                    " -o|-O OutputFile [-h]\n\n"
        "   -V|--version            - Version\n"
        "   -h|--help               - Help screen\n"
        "   -f InputFile            - Input file name\n"
        "   -o OutputFile           - Ouput file name (don't overwrite if exists)\n"
        "   -O OutputFile           - Ouput file name (overwrite if exists)\n"
        "   -s|--start StartPktNum  - Starting packet number (counting from 1)\n"
        "   -e|--end   EndPktNum    - Ending packet number (must be >= StartPktNum)\n"
        "   -n|--num   TotNumPkts   - Number of packets to save\n"
        "   -r|--raw                - Output raw packet payload only without pcap format\n"
        "   -c|--count              - Count number of packets in the file\n"
        "   -v                      - Verbose\n\n";
    }

    exit(1);
}

//------------------------------------------------------------------------------
void unhandled_exception() {
  auto p = current_exception();
  try    { rethrow_exception(p); }
  catch  ( exception& e ) { cerr << e.what() << endl; }
  catch  ( ... )          { cerr << "Unknown exception" << endl; }
  exit(1);
}

//------------------------------------------------------------------------------
//  MAIN
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    string in_file;
    string out_file;
    size_t pk_start  = 1, pk_end = 0, pk_cnt = 0;
    bool   overwrite = false;
    bool   raw_mode  = false;
    bool   count     = false;
    bool   verbose   = false;

    set_terminate (&unhandled_exception);

    utxx::opts_parser opts(argc, argv);

    while (opts.next()) {
        if (opts.match("-f", "",        &in_file))  continue;
        if (opts.match("-o", "",        &out_file)) continue;
        if (opts.match("-O", "",        &out_file)){overwrite=true; continue;}
        if (opts.match("-r", "--raw",   &raw_mode)) continue;
        if (opts.match("-s", "--start", &pk_start)) continue;
        if (opts.match("-e", "--end",   &pk_end))   continue;
        if (opts.match("-n", "--num",   &pk_cnt))   continue;
        if (opts.match("-c", "--count", &count))    continue;
        if (opts.match("-v", "",        &verbose))  continue;
        if (opts.match("-V", "--version")) throw std::runtime_error(VERSION());
        if (opts.is_help())                         usage();

        usage(opts());
    }

    if (pk_end > 0 && pk_cnt > 0)
        throw std::runtime_error("Cannot specify both -n and -e options!");
    else if (!pk_end && !pk_cnt && !count)
        throw std::runtime_error("Must specify either -n or -e option!");
    else if (!pk_start && !count)
        throw std::runtime_error("PktStartNumber (-s) must be greater than 0!");
    else if (pk_end && pk_end < pk_start)
        throw std::runtime_error
             ("Ending packet number (-e) must not be less than starting packet number (-s)!");
    else if (in_file.empty() || (!count && out_file.empty()))
        throw std::runtime_error("Must specify -f and -o options!");
    else if (!count && utxx::path::file_exists(out_file)) {
        if (!overwrite)
            throw std::runtime_error("Found existing output file: " + out_file);
        if (!utxx::path::file_unlink(out_file))
            throw std::runtime_error("Error deleting file " + out_file +
                                     ": " + strerror(errno));
    }

    if (pk_cnt) {
        pk_end = pk_start + pk_cnt - 1;
        pk_cnt = 0;
    }

    utxx::pcap fin;
    if (fin.open_read(in_file) < 0)
        throw std::runtime_error("Error opening " + in_file + ": " + strerror(errno));
    else if (fin.read_file_header() < 0)
        throw std::runtime_error("File " + in_file + " is not in PCAP format!");

    int n = 0;
    utxx::pcap fout(fin.big_endian(), fin.nsec_time());

    if (!count) {
        n = raw_mode ? fout.open(out_file.c_str(), "wb")
                    : fout.open_write(out_file, false, fin.get_link_type());
        if (n < 0)
            throw std::runtime_error("Error creating file " + out_file + ": " + strerror(errno));
    }

    utxx::basic_io_buffer<(1024*1024)> buf;

    while ((n = fin.read(buf.wr_ptr(), buf.capacity())) > 0) {
        buf.commit(n);
        if (verbose)
            cerr << "Read "    << n   << " bytes from source file (offset="
                 << fin.tell() << ')' << endl;

        while (buf.size() > sizeof(utxx::pcap::packet_header)) {
            const char*       header;
            const char*       begin  = header = buf.rd_ptr();
            int               frame_sz, sz;
            utxx::pcap::proto proto;

            // sz - total size of payload including frame_sz
            std::tie(frame_sz, sz, proto) = fin.read_packet_hdr_and_frame(begin, n);

            if (frame_sz < 0 || int(buf.size()) < sz) { // Not enough data in the buffer
                if (verbose && frame_sz < 0)
                    cerr << "Pkt#" << (pk_cnt+1) << ": Cannot read frame size of packet\n";
                buf.reserve(sz);
                break;
            }

            if (verbose)
                cerr << "Pkt#"      << (pk_cnt+1)   << " FrameSz=" << setw(2)    << frame_sz
                     << " Bytes="   << sz           << " BufSz="   << buf.size()
                     << " (BufPos=" << buf.rd_ptr() << ')'         << endl;

            if (++pk_cnt >= pk_start && !count) {
                if (pk_cnt > pk_end)
                    goto DONE;

                // Write to the output file
                if (!raw_mode) {
                    fout.write_packet_header(fin.packet());
                    buf.read(sizeof(utxx::pcap::packet_header));
                    sz    -= sizeof(utxx::pcap::packet_header);
                } else {
                    buf.read(frame_sz);
                    sz    -= frame_sz;
                }
                if (fout.write(buf.rd_ptr(), sz) < 0)
                    throw std::runtime_error(string("Error writing to file: ") + strerror(errno));
            }

            buf.read(sz);
        }

        buf.crunch();
    }

  DONE:
    fout.close();
    fin.close();

    if (count)
        cout << pk_cnt << " packets\n";

    return 0;
}<|endoftext|>


<commit_before>/*
 * Copyright 2007-2022 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#ifdef NDEBUG

#define TYPE_ARG_DECL
#define TYPE_ARG_FWD
#define TYPE_ARG_NULL
#define TYPE_ARG(T)

#else

#include <boost/type_index.hpp>

#define TYPE_ARG_DECL , const char *type
#define TYPE_ARG_FWD , type
#define TYPE_ARG_NULL , nullptr
#define TYPE_ARG(T) , boost::typeindex::type_id<T>().name()

#endif
<commit_msg>pool/Type: use typeid() instead of boost::typeindex<commit_after>/*
 * Copyright 2007-2022 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#ifdef NDEBUG

#define TYPE_ARG_DECL
#define TYPE_ARG_FWD
#define TYPE_ARG_NULL
#define TYPE_ARG(T)

#else

#include <typeinfo>

#define TYPE_ARG_DECL , const char *type
#define TYPE_ARG_FWD , type
#define TYPE_ARG_NULL , nullptr
#define TYPE_ARG(T) , typeid(T).name()

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2016, Baidu.com, Inc. All Rights Reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#define private public
#include "chunkserver/block_manager.h"
#include "chunkserver/data_block.h"

#include <gflags/gflags.h>
#include <gtest/gtest.h>

DECLARE_string(namedb_path);
DECLARE_int32(write_buf_size);

namespace baidu {
namespace bfs {

void sleep_task() {
    int32_t sleep_time = rand() % 3 + 1;
    sleep(sleep_time);
}

void write_task(Block* block, int32_t seq, int64_t offset, std::string write_data) {
    block->Write(seq, offset, write_data.data(), write_data.size(), NULL);
}

class BlockManagerTest : public ::testing::Test {
public:
    BlockManagerTest() {}
protected:
};

TEST_F(BlockManagerTest, RemoveBlock) {
    mkdir("./test_dir", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    BlockManager block_manager("./test_dir");
    bool ret = block_manager.LoadStorage();
    ASSERT_TRUE(ret);

    //normal case
    int64_t block_id = 123;
    int64_t sync_time;
    StatusCode status;
    Block* block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    std::string disk_file_path = block->disk_file_;
    // now ref count for block is 2
    ret = block->Write(0, 0, NULL, 0, NULL);
    ASSERT_TRUE(ret);
    FLAGS_write_buf_size = 5;
    std::string test_write_data("hello world");
    ret = block->Write(1, 0, test_write_data.data(), test_write_data.size(), NULL);
    ASSERT_TRUE(ret);
    block_manager.CloseBlock(block);
    //after RemoveBlock, ref count for block is 1
    block_manager.RemoveBlock(block_id);
    ASSERT_EQ(block->refs_, 1);
    ASSERT_EQ(block->deleted_, true);
    struct stat st;
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) == 0);
    //after the last ref is released, disk file should be removed
    block->DecRef();
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);

    // close before write
    block_id = 456;
    block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    block_manager.CloseBlock(block);
    ASSERT_EQ(block->finished_, true);
    ASSERT_EQ(block->file_desc_, Block::kClosed);
    block_manager.RemoveBlock(block_id);
    ASSERT_EQ(block->refs_, 1);
    ASSERT_EQ(block->deleted_, 1);
    disk_file_path = block->disk_file_;
    block->DecRef();
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);

    // delete before write
    block_id = 789;
    block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    block_manager.RemoveBlock(block_id);
    ASSERT_EQ(block->refs_, 1);
    ASSERT_EQ(block->deleted_, true);
    ASSERT_EQ(block->finished_, false);
    ASSERT_EQ(block->file_desc_, Block::kNotCreated);
    // Write will fail
    ret = block->Write(0, 0, NULL, 0, NULL);
    ASSERT_EQ(ret, false);
    disk_file_path = block->meta_.store_path() + Block::BuildFilePath(block_id);
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);
    block->DecRef();
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);

    rmdir("./test_dir");
}

TEST_F(BlockManagerTest, Out_of_order) {
    ThreadPool thread_pool(10);
    mkdir("./test_dir", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    BlockManager block_manager("./test_dir");
    bool ret = block_manager.LoadStorage();
    ASSERT_TRUE(ret);
    StatusCode status;
    int64_t block_id = 123;
    int64_t sync_time;
    //after create, ref for this block is 2
    Block* block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    // we will use thread pool and closure to operate this block
    // first hold all threads
    for (int i = 0; i < 10; i++) {
        thread_pool.AddTask(std::bind(sleep_task));
    }
    //then add tasks to normal or priority queue, write/close/remove tasks will be out-of-order
    FLAGS_write_buf_size = 5;
    std::string test_data("hello world");
    srand(time(NULL));
    int32_t r = rand() % 2;
    std::function<void ()> write_data_task1 = std::bind(write_task, block, 0, 0, "");
    std::function<void ()> write_data_task2 = std::bind(write_task, block, 0, 0, test_data);
    if (r == 0) {
        thread_pool.AddTask(write_data_task1);
        thread_pool.AddTask(write_data_task2);
    } else {
        thread_pool.AddPriorityTask(write_data_task1);
        thread_pool.AddPriorityTask(write_data_task2);
    }

    std::function<void()> close_task = std::bind(&BlockManager::CloseBlock, &block_manager, block);
    r = rand() % 2;
    if (r == 0) {
        thread_pool.AddTask(close_task);
    } else {
        thread_pool.AddPriorityTask(close_task);
    }

    std::function<void()> remove_task = std::bind(&BlockManager::RemoveBlock, &block_manager, block_id);
    r = rand() % 2;
    if (r == 0) {
        thread_pool.AddTask(remove_task);
    } else {
        thread_pool.AddPriorityTask(remove_task);
    }

    //wait for all tasks run
    thread_pool.Stop(true);
    block->DecRef();
    rmdir("./test_dir");
}

}
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
<commit_msg>fix unit test case<commit_after>// Copyright (c) 2016, Baidu.com, Inc. All Rights Reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#define private public
#include "chunkserver/block_manager.h"
#include "chunkserver/data_block.h"

#include <gflags/gflags.h>
#include <gtest/gtest.h>

DECLARE_string(namedb_path);
DECLARE_int32(write_buf_size);

namespace baidu {
namespace bfs {

void sleep_task() {
    sleep(1);
}

void write_task(Block* block, int32_t seq, int64_t offset, std::string write_data) {
    block->Write(seq, offset, write_data.data(), write_data.size(), NULL);
}

class BlockManagerTest : public ::testing::Test {
public:
    BlockManagerTest() {}
protected:
};

TEST_F(BlockManagerTest, RemoveBlock) {
    mkdir("./test_dir", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    BlockManager block_manager("./test_dir");
    bool ret = block_manager.LoadStorage();
    ASSERT_TRUE(ret);

    //normal case
    int64_t block_id = 123;
    int64_t sync_time;
    StatusCode status;
    Block* block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    std::string disk_file_path = block->disk_file_;
    // now ref count for block is 2
    ret = block->Write(0, 0, NULL, 0, NULL);
    ASSERT_TRUE(ret);
    FLAGS_write_buf_size = 5;
    std::string test_write_data("hello world");
    ret = block->Write(1, 0, test_write_data.data(), test_write_data.size(), NULL);
    ASSERT_TRUE(ret);
    block_manager.CloseBlock(block);
    //after RemoveBlock, ref count for block is 1
    block_manager.RemoveBlock(block_id);
    ASSERT_EQ(block->refs_, 1);
    ASSERT_EQ(block->deleted_, true);
    struct stat st;
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) == 0);
    //after the last ref is released, disk file should be removed
    block->DecRef();
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);

    // close before write
    block_id = 456;
    block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    block_manager.CloseBlock(block);
    ASSERT_EQ(block->finished_, true);
    ASSERT_EQ(block->file_desc_, Block::kClosed);
    block_manager.RemoveBlock(block_id);
    ASSERT_EQ(block->refs_, 1);
    ASSERT_EQ(block->deleted_, 1);
    disk_file_path = block->disk_file_;
    block->DecRef();
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);

    // delete before write
    block_id = 789;
    block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    block_manager.RemoveBlock(block_id);
    ASSERT_EQ(block->refs_, 1);
    ASSERT_EQ(block->deleted_, true);
    ASSERT_EQ(block->finished_, false);
    ASSERT_EQ(block->file_desc_, Block::kNotCreated);
    // Write will fail
    ret = block->Write(0, 0, NULL, 0, NULL);
    ASSERT_EQ(ret, false);
    disk_file_path = block->meta_.store_path() + Block::BuildFilePath(block_id);
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);
    block->DecRef();
    ASSERT_TRUE(stat(disk_file_path.c_str(), &st) != 0);
    ASSERT_EQ(errno, ENOENT);

    rmdir("./test_dir");
}

TEST_F(BlockManagerTest, Out_of_order) {
    ThreadPool thread_pool(10);
    mkdir("./test_dir", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    BlockManager block_manager("./test_dir");
    bool ret = block_manager.LoadStorage();
    ASSERT_TRUE(ret);
    StatusCode status;
    int64_t block_id = 123;
    int64_t sync_time;
    //after create, ref for this block is 2
    Block* block = block_manager.CreateBlock(block_id, &sync_time, &status);
    ASSERT_TRUE(block != NULL);
    // we will use thread pool and closure to operate this block
    // first hold all threads
    for (int i = 0; i < 10; i++) {
        thread_pool.AddTask(std::bind(sleep_task));
    }
    //then add tasks to normal or priority queue, write/close/remove tasks will be out-of-order
    FLAGS_write_buf_size = 5;
    std::string test_data("hello world");
    srand(time(NULL));
    int32_t r = rand() % 2;
    std::function<void ()> write_data_task1 = std::bind(write_task, block, 0, 0, "");
    std::function<void ()> write_data_task2 = std::bind(write_task, block, 1, 0, test_data);
    if (r == 0) {
        thread_pool.AddTask(write_data_task1);
        thread_pool.AddTask(write_data_task2);
    } else {
        thread_pool.AddPriorityTask(write_data_task1);
        thread_pool.AddPriorityTask(write_data_task2);
    }

    std::function<void()> close_task = std::bind(&BlockManager::CloseBlock, &block_manager, block);
    r = rand() % 2;
    if (r == 0) {
        thread_pool.AddTask(close_task);
    } else {
        thread_pool.AddPriorityTask(close_task);
    }

    std::function<void()> remove_task = std::bind(&BlockManager::RemoveBlock, &block_manager, block_id);
    r = rand() % 2;
    if (r == 0) {
        thread_pool.AddTask(remove_task);
    } else {
        thread_pool.AddPriorityTask(remove_task);
    }

    //wait for all tasks run
    thread_pool.Stop(true);
    block->DecRef();
    rmdir("./test_dir");
}

}
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
<|endoftext|>


<commit_before>#include "utf8_cleanup.h"

//code from pugixml.cpp
//Copyright (C) 2006-2017, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)

struct utf8_writer
{
    typedef uint8_t* value_type;

    static value_type low(value_type result, uint32_t ch)
    {
        // U+0000..U+007F
        if (ch < 0x80)
        {
            *result = static_cast<uint8_t>(ch);
            return result + 1;
        }
        // U+0080..U+07FF
        else if (ch < 0x800)
        {
            result[0] = static_cast<uint8_t>(0xC0 | (ch >> 6));
            result[1] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
            return result + 2;
        }
        // U+0800..U+FFFF (U+0800..U+FDCF, U+FDF0..U+FFFD)
        else if (ch < 0xfdd0 || (ch > 0xfdef && ch < 0xfffe))
        {
            result[0] = static_cast<uint8_t>(0xE0 | (ch >> 12));
            result[1] = static_cast<uint8_t>(0x80 | ((ch >> 6) & 0x3F));
            result[2] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
            return result + 3;
        }

        return result;
    }

    static value_type high(value_type result, uint32_t ch)
    {
        // U+10000..U+10FFFF
        result[0] = static_cast<uint8_t>(0xF0 | (ch >> 18));
        result[1] = static_cast<uint8_t>(0x80 | ((ch >> 12) & 0x3F));
        result[2] = static_cast<uint8_t>(0x80 | ((ch >> 6) & 0x3F));
        result[3] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
        return result + 4;
    }

    static value_type any(value_type result, uint32_t ch)
    {
        return (ch < 0x10000) ? low(result, ch) : high(result, ch);
    }
};

struct utf8_decoder
{
    typedef uint8_t type;

    template <typename Traits> static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits)
    {
        const uint8_t utf8_byte_mask = 0x3f;

        while (size)
        {
            uint8_t lead = *data;

            // 0xxxxxxx -> U+0000..U+007F
            if (lead < 0x80)
            {
                result = Traits::low(result, lead);
                data += 1;
                size -= 1;

                // process aligned single-byte (ascii) blocks
                if ((reinterpret_cast<uintptr_t>(data) & 3) == 0)
                {
                    // round-trip through void* to silence 'cast increases required alignment of target type' warnings
                    while (size >= 4 && (*static_cast<const uint32_t*>(static_cast<const void*>(data)) & 0x80808080) == 0)
                    {
                        result = Traits::low(result, data[0]);
                        result = Traits::low(result, data[1]);
                        result = Traits::low(result, data[2]);
                        result = Traits::low(result, data[3]);
                        data += 4;
                        size -= 4;
                    }
                }
            }
            // 110xxxxx -> U+0080..U+07FF
            else if (static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80)
            {
                result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
                data += 2;
                size -= 2;
            }
            // 1110xxxx -> U+0800-U+FFFF
            else if (static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
            {
                result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
                data += 3;
                size -= 3;
            }
            // 11110xxx -> U+10000..U+10FFFF
            else if (static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
            {
                result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
                data += 4;
                size -= 4;
            }
            // 10xxxxxx or 11111xxx -> invalid
            else
            {
                data += 1;
                size -= 1;
            }
        }

        return result;
    }
};

size_t utf8_cleanup(char* buffer, size_t length)
{
    uint8_t* obegin = reinterpret_cast<uint8_t*>(buffer);
    uint8_t* oend = utf8_decoder::process(obegin, length, obegin, utf8_writer());
    return oend - obegin;
}
<commit_msg>Update comment<commit_after>#include "utf8_cleanup.h"

//code from pugixml.cpp
//Copyright (C) 2006-2017, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
//modified to strip some invalid unicode intervals

struct utf8_writer
{
    typedef uint8_t* value_type;

    static value_type low(value_type result, uint32_t ch)
    {
        // U+0000..U+007F
        if (ch < 0x80)
        {
            *result = static_cast<uint8_t>(ch);
            return result + 1;
        }
        // U+0080..U+07FF
        else if (ch < 0x800)
        {
            result[0] = static_cast<uint8_t>(0xC0 | (ch >> 6));
            result[1] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
            return result + 2;
        }
        // U+0800..U+FFFF (U+0800..U+FDCF, U+FDF0..U+FFFD)
        else if (ch < 0xfdd0 || (ch > 0xfdef && ch < 0xfffe))
        {
            result[0] = static_cast<uint8_t>(0xE0 | (ch >> 12));
            result[1] = static_cast<uint8_t>(0x80 | ((ch >> 6) & 0x3F));
            result[2] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
            return result + 3;
        }

        return result;
    }

    static value_type high(value_type result, uint32_t ch)
    {
        // U+10000..U+10FFFF
        result[0] = static_cast<uint8_t>(0xF0 | (ch >> 18));
        result[1] = static_cast<uint8_t>(0x80 | ((ch >> 12) & 0x3F));
        result[2] = static_cast<uint8_t>(0x80 | ((ch >> 6) & 0x3F));
        result[3] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
        return result + 4;
    }

    static value_type any(value_type result, uint32_t ch)
    {
        return (ch < 0x10000) ? low(result, ch) : high(result, ch);
    }
};

struct utf8_decoder
{
    typedef uint8_t type;

    template <typename Traits> static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits)
    {
        const uint8_t utf8_byte_mask = 0x3f;

        while (size)
        {
            uint8_t lead = *data;

            // 0xxxxxxx -> U+0000..U+007F
            if (lead < 0x80)
            {
                result = Traits::low(result, lead);
                data += 1;
                size -= 1;

                // process aligned single-byte (ascii) blocks
                if ((reinterpret_cast<uintptr_t>(data) & 3) == 0)
                {
                    // round-trip through void* to silence 'cast increases required alignment of target type' warnings
                    while (size >= 4 && (*static_cast<const uint32_t*>(static_cast<const void*>(data)) & 0x80808080) == 0)
                    {
                        result = Traits::low(result, data[0]);
                        result = Traits::low(result, data[1]);
                        result = Traits::low(result, data[2]);
                        result = Traits::low(result, data[3]);
                        data += 4;
                        size -= 4;
                    }
                }
            }
            // 110xxxxx -> U+0080..U+07FF
            else if (static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80)
            {
                result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
                data += 2;
                size -= 2;
            }
            // 1110xxxx -> U+0800-U+FFFF
            else if (static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
            {
                result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
                data += 3;
                size -= 3;
            }
            // 11110xxx -> U+10000..U+10FFFF
            else if (static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
            {
                result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
                data += 4;
                size -= 4;
            }
            // 10xxxxxx or 11111xxx -> invalid
            else
            {
                data += 1;
                size -= 1;
            }
        }

        return result;
    }
};

size_t utf8_cleanup(char* buffer, size_t length)
{
    uint8_t* obegin = reinterpret_cast<uint8_t*>(buffer);
    uint8_t* oend = utf8_decoder::process(obegin, length, obegin, utf8_writer());
    return oend - obegin;
}
<|endoftext|>


<commit_before>/* dtkComposerSceneNodeLeaf.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008-2011 - Julien Wintz, Inria.
 * Created: Fri Feb  3 14:02:14 2012 (+0100)
 * Version: $Id$
 * Last-Updated: Mon Jul  9 13:58:46 2012 (+0200)
 *           By: tkloczko
 *     Update #: 248
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerNode.h"
#include "dtkComposerNodeLeafData.h"
#include "dtkComposerNodeLeafProcess.h"
#include "dtkComposerNodeLeafView.h"
#include "dtkComposerSceneNode.h"
#include "dtkComposerSceneNode_p.h"
#include "dtkComposerSceneNodeLeaf.h"
#include "dtkComposerScenePort.h"
#include "dtkComposerTransmitter.h"

class dtkComposerSceneNodeLeafPrivate
{
public:
    QRectF rect;

public:
    qreal min_height;
};

dtkComposerSceneNodeLeaf::dtkComposerSceneNodeLeaf(void) : dtkComposerSceneNode(), d(new dtkComposerSceneNodeLeafPrivate)
{
    d->min_height = 50;

    d->rect = QRectF(0, 0, 150, 50);
}

dtkComposerSceneNodeLeaf::~dtkComposerSceneNodeLeaf(void)
{
    delete d;

    d = NULL;
}

void dtkComposerSceneNodeLeaf::wrap(dtkComposerNode *node)
{
    dtkComposerSceneNode::wrap(node);

    //foreach(dtkComposerTransmitter *receiver, node->receivers()) {

    for(int i = 0; i < node->receivers().count(); ++i) {

        dtkComposerScenePort *port = new dtkComposerScenePort(dtkComposerScenePort::Input, this);
        this->addInputPort(port);
        port->setLabel(node->inputLabelHint(this->inputPorts().indexOf(port)));

    }

    //foreach(dtkComposerTransmitter *emitter, node->emitters()) {
    for(int i = 0; i < node->emitters().count(); ++i) {

        dtkComposerScenePort *port = new dtkComposerScenePort(dtkComposerScenePort::Output, this);
        this->addOutputPort(port);
        port->setLabel(node->outputLabelHint(this->outputPorts().indexOf(port)));

    }

    this->layout();
}

#include "dtkComposerSceneNodeComposite.h"
#include "dtkComposerSceneNodeControl.h"

void dtkComposerSceneNodeLeaf::layout(void)
{
    int header = this->embedded() ? 0 : 15;

    int port_margin_top = 10;
    int port_margin_bottom = 10;
    int port_margin_left = 10;
    int port_spacing = 10;

// /////////////////////////////////////////////////////////////////
// Setting up port position
// /////////////////////////////////////////////////////////////////

    for(int i = 0; i < this->inputPorts().count(); i++)
        this->inputPorts().at(i)->setPos(QPointF(port_margin_left, i*this->inputPorts().at(i)->boundingRect().height() + i*port_spacing + port_margin_top + header));

    for(int i = 0; i < this->outputPorts().count(); i++)
        this->outputPorts().at(i)->setPos(QPointF(d->rect.right() - port_margin_left - this->outputPorts().at(i)->boundingRect().width(), i*this->outputPorts().at(i)->boundingRect().height() + i*port_spacing + port_margin_top + header));

// /////////////////////////////////////////////////////////////////
// Height calculation
// /////////////////////////////////////////////////////////////////

    if(this->inputPorts().count() || this->outputPorts().count())
        if(this->inputPorts().count() >= this->outputPorts().count())
            d->rect = QRectF(d->rect.topLeft(), QSize(d->rect.width(), this->inputPorts().count() * this->inputPorts().at(0)->boundingRect().height() + port_margin_top + port_margin_bottom + (this->inputPorts().count()-1) * port_spacing + header));
        else
            d->rect = QRectF(d->rect.topLeft(), QSize(d->rect.width(), this->outputPorts().count() * this->outputPorts().at(0)->boundingRect().height() + port_margin_top + port_margin_bottom + (this->outputPorts().count()-1) * port_spacing + header));

    else if(this->embedded())
        d->rect = QRectF(d->rect.topLeft(), QSize(d->rect.width(), port_margin_top + port_margin_bottom + 10));

// /////////////////////////////////////////////////////////////////
// Redraw parent
// /////////////////////////////////////////////////////////////////

    if (dtkComposerSceneNodeComposite *parent = dynamic_cast<dtkComposerSceneNodeComposite *>(this->parent())) {
        if(!parent->root()) {
            if (parent->entered() || (parent->flattened() && !parent->embedded())) {
                parent->layout();
            }
        }
    }

// /////////////////////////////////////////////////////////////////
// Update edges geometry
// /////////////////////////////////////////////////////////////////

    QRectF updateRect;

    foreach(dtkComposerSceneEdge *edge, this->inputEdges()) {
        edge->adjust();
        updateRect |= edge->boundingRect();
    }

    foreach(dtkComposerSceneEdge *edge, this->outputEdges()) {
        edge->adjust();
        updateRect |= edge->boundingRect();
    }

    this->update(updateRect);
}

void dtkComposerSceneNodeLeaf::resize(qreal width, qreal height)
{
    d->rect = QRectF(d->rect.topLeft(), QSizeF(width, height));
}

QRectF dtkComposerSceneNodeLeaf::boundingRect(void) const
{
    return d->rect.adjusted(-2, -2, 2, 2);
}

void dtkComposerSceneNodeLeaf::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    qreal radius = this->embedded() ? 0.0 : 5.0;

    if (this->isSelected()) {
        painter->setPen(QPen(Qt::magenta, 2, Qt::SolidLine));
        painter->setBrush(Qt::NoBrush);
        painter->drawRoundedRect(d->rect.adjusted(-2, -2, 2, 2), radius, radius);
    }

    if(this->embedded())
        painter->setPen(Qt::NoPen);
    else
        painter->setPen(QPen(Qt::black, 1, Qt::SolidLine));

    QLinearGradient gradiant(d->rect.left(), d->rect.top(), d->rect.left(), d->rect.bottom());

    qreal height = qAbs(d->rect.top() - d->rect.bottom());

    qreal stripe = 0.2 * (d->min_height) / height;

    if (dynamic_cast<dtkComposerNodeLeafProcess*>(this->wrapee())) {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(Qt::red));
        gradiant.setColorAt(1.0, QColor(Qt::red).darker());
    } else if (dynamic_cast<dtkComposerNodeLeafData*>(this->wrapee())) {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(Qt::blue));
        gradiant.setColorAt(1.0, QColor(Qt::blue).darker());
    } else if (dynamic_cast<dtkComposerNodeLeafView*>(this->wrapee())) {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(Qt::green));
        gradiant.setColorAt(1.0, QColor(Qt::green).darker());
    } else {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(Qt::gray));
        gradiant.setColorAt(1.0, QColor(Qt::gray).darker());
    }

    painter->setBrush(gradiant);

    painter->drawRoundedRect(d->rect, radius, radius);

    // Drawing node's title

    qreal margin = 5.0;

    QFont font = painter->font();
    QFontMetricsF metrics(font);
    QString title_text = metrics.elidedText(this->title(), Qt::ElideMiddle, this->boundingRect().width()-2-4*margin);

    QPointF title_pos;

    if(!this->embedded())
        title_pos = QPointF(2*margin, 2*margin + metrics.xHeight());
    else
        title_pos = QPointF(d->rect.right() - 2*margin - metrics.width(title_text), 2*margin + metrics.xHeight());

    painter->setPen(QPen(QColor(Qt::gray).darker()));
    painter->drawText(title_pos + QPointF(0, -1), title_text);
    painter->setPen(QPen(QColor(Qt::gray)));
    painter->drawText(title_pos + QPointF(0, 1), title_text);
    painter->setPen(QPen(QColor(Qt::white)));
    painter->drawText(title_pos, title_text);
}
<commit_msg>Enhanced node coxlors.<commit_after>/* dtkComposerSceneNodeLeaf.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008-2011 - Julien Wintz, Inria.
 * Created: Fri Feb  3 14:02:14 2012 (+0100)
 * Version: $Id$
 * Last-Updated: Tue Jul 10 12:19:59 2012 (+0200)
 *           By: tkloczko
 *     Update #: 277
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerNode.h"
#include "dtkComposerNodeLeafData.h"
#include "dtkComposerNodeLeafProcess.h"
#include "dtkComposerNodeLeafView.h"
#include "dtkComposerSceneNode.h"
#include "dtkComposerSceneNode_p.h"
#include "dtkComposerSceneNodeLeaf.h"
#include "dtkComposerScenePort.h"
#include "dtkComposerTransmitter.h"

class dtkComposerSceneNodeLeafPrivate
{
public:
    QRectF rect;

public:
    qreal min_height;
};

dtkComposerSceneNodeLeaf::dtkComposerSceneNodeLeaf(void) : dtkComposerSceneNode(), d(new dtkComposerSceneNodeLeafPrivate)
{
    d->min_height = 50;

    d->rect = QRectF(0, 0, 150, 50);
}

dtkComposerSceneNodeLeaf::~dtkComposerSceneNodeLeaf(void)
{
    delete d;

    d = NULL;
}

void dtkComposerSceneNodeLeaf::wrap(dtkComposerNode *node)
{
    dtkComposerSceneNode::wrap(node);

    //foreach(dtkComposerTransmitter *receiver, node->receivers()) {

    for(int i = 0; i < node->receivers().count(); ++i) {

        dtkComposerScenePort *port = new dtkComposerScenePort(dtkComposerScenePort::Input, this);
        this->addInputPort(port);
        port->setLabel(node->inputLabelHint(this->inputPorts().indexOf(port)));

    }

    //foreach(dtkComposerTransmitter *emitter, node->emitters()) {
    for(int i = 0; i < node->emitters().count(); ++i) {

        dtkComposerScenePort *port = new dtkComposerScenePort(dtkComposerScenePort::Output, this);
        this->addOutputPort(port);
        port->setLabel(node->outputLabelHint(this->outputPorts().indexOf(port)));

    }

    this->layout();
}

#include "dtkComposerSceneNodeComposite.h"
#include "dtkComposerSceneNodeControl.h"

void dtkComposerSceneNodeLeaf::layout(void)
{
    int header = this->embedded() ? 0 : 15;

    int port_margin_top = 10;
    int port_margin_bottom = 10;
    int port_margin_left = 10;
    int port_spacing = 10;

// /////////////////////////////////////////////////////////////////
// Setting up port position
// /////////////////////////////////////////////////////////////////

    for(int i = 0; i < this->inputPorts().count(); i++)
        this->inputPorts().at(i)->setPos(QPointF(port_margin_left, i*this->inputPorts().at(i)->boundingRect().height() + i*port_spacing + port_margin_top + header));

    for(int i = 0; i < this->outputPorts().count(); i++)
        this->outputPorts().at(i)->setPos(QPointF(d->rect.right() - port_margin_left - this->outputPorts().at(i)->boundingRect().width(), i*this->outputPorts().at(i)->boundingRect().height() + i*port_spacing + port_margin_top + header));

// /////////////////////////////////////////////////////////////////
// Height calculation
// /////////////////////////////////////////////////////////////////

    if(this->inputPorts().count() || this->outputPorts().count())
        if(this->inputPorts().count() >= this->outputPorts().count())
            d->rect = QRectF(d->rect.topLeft(), QSize(d->rect.width(), this->inputPorts().count() * this->inputPorts().at(0)->boundingRect().height() + port_margin_top + port_margin_bottom + (this->inputPorts().count()-1) * port_spacing + header));
        else
            d->rect = QRectF(d->rect.topLeft(), QSize(d->rect.width(), this->outputPorts().count() * this->outputPorts().at(0)->boundingRect().height() + port_margin_top + port_margin_bottom + (this->outputPorts().count()-1) * port_spacing + header));

    else if(this->embedded())
        d->rect = QRectF(d->rect.topLeft(), QSize(d->rect.width(), port_margin_top + port_margin_bottom + 10));

// /////////////////////////////////////////////////////////////////
// Redraw parent
// /////////////////////////////////////////////////////////////////

    if (dtkComposerSceneNodeComposite *parent = dynamic_cast<dtkComposerSceneNodeComposite *>(this->parent())) {
        if(!parent->root()) {
            if (parent->entered() || (parent->flattened() && !parent->embedded())) {
                parent->layout();
            }
        }
    }

// /////////////////////////////////////////////////////////////////
// Update edges geometry
// /////////////////////////////////////////////////////////////////

    QRectF updateRect;

    foreach(dtkComposerSceneEdge *edge, this->inputEdges()) {
        edge->adjust();
        updateRect |= edge->boundingRect();
    }

    foreach(dtkComposerSceneEdge *edge, this->outputEdges()) {
        edge->adjust();
        updateRect |= edge->boundingRect();
    }

    this->update(updateRect);
}

void dtkComposerSceneNodeLeaf::resize(qreal width, qreal height)
{
    d->rect = QRectF(d->rect.topLeft(), QSizeF(width, height));
}

QRectF dtkComposerSceneNodeLeaf::boundingRect(void) const
{
    return d->rect.adjusted(-2, -2, 2, 2);
}

void dtkComposerSceneNodeLeaf::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    qreal radius = this->embedded() ? 0.0 : 5.0;

    if (this->isSelected()) {
        painter->setPen(QPen(Qt::magenta, 2, Qt::SolidLine));
        painter->setBrush(Qt::NoBrush);
        painter->drawRoundedRect(d->rect.adjusted(-2, -2, 2, 2), radius, radius);
    }

    if(this->embedded())
        painter->setPen(Qt::NoPen);
    else
        painter->setPen(QPen(Qt::black, 1, Qt::SolidLine));

    QLinearGradient gradiant(d->rect.left(), d->rect.top(), d->rect.left(), d->rect.bottom());

    qreal height = qAbs(d->rect.top() - d->rect.bottom());
    qreal stripe = 0.15 * (d->min_height) / height;

    if (dynamic_cast<dtkComposerNodeLeafProcess*>(this->wrapee())) {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(225, 0, 0));
        gradiant.setColorAt(1.0, QColor(Qt::red).darker());
    } else if (dynamic_cast<dtkComposerNodeLeafData*>(this->wrapee())) {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(10, 10, 255));
        gradiant.setColorAt(1.0, QColor(Qt::blue).darker());
    } else if (dynamic_cast<dtkComposerNodeLeafView*>(this->wrapee())) {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(0, 220, 0));
        gradiant.setColorAt(1.0, QColor(Qt::green).darker());
    } else {
        gradiant.setColorAt(0.0, QColor(Qt::white));
        gradiant.setColorAt(stripe, QColor(Qt::gray));
        gradiant.setColorAt(1.0, QColor(Qt::gray).darker());
    }

    qDebug() << stripe * height;

    painter->setBrush(gradiant);

    painter->drawRoundedRect(d->rect, radius, radius);

    // Drawing node's title

    qreal margin = 5.0;

    QFont font = painter->font();
    QFontMetricsF metrics(font);
    QString title_text = metrics.elidedText(this->title(), Qt::ElideMiddle, this->boundingRect().width()-2-4*margin);

    QPointF title_pos;

    if(!this->embedded())
        title_pos = QPointF(2*margin, 2*margin + metrics.xHeight());
    else
        title_pos = QPointF(d->rect.right() - 2*margin - metrics.width(title_text), 2*margin + metrics.xHeight());

    painter->setPen(QPen(QColor(Qt::gray).darker()));
    painter->drawText(title_pos + QPointF(0, -1), title_text);
    painter->setPen(QPen(QColor(Qt::gray)));
    painter->drawText(title_pos + QPointF(0, 1), title_text);
    painter->setPen(QPen(QColor(Qt::white)));
    painter->drawText(title_pos, title_text);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: javavm.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: sb $ $Date: 2002-12-06 10:48:58 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source 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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#if !defined INCLUDED_STOC_JAVAVM_JAVAVM_HXX
#define INCLUDED_STOC_JAVAVM_JAVAVM_HXX

#include "jvmargs.hxx"

#include "com/sun/star/container/XContainerListener.hpp"
#include "com/sun/star/lang/XInitialization.hpp"
#include "com/sun/star/java/XJavaThreadRegister_11.hpp"
#include "com/sun/star/java/XJavaVM.hpp"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "cppuhelper/compbase5.hxx"
#include "osl/module.hxx"
#include "osl/thread.hxx"
#include "rtl/ref.hxx"

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace container { class XContainer; }
    namespace uno { class XComponentContext; }
} } }
namespace jvmaccess { class VirtualMachine; }

namespace stoc_javavm {

// The MS compiler needs a typedef here, so the JavaVirtualMachine ctor can call
// its base class ctor:
typedef
cppu::WeakComponentImplHelper5< com::sun::star::lang::XInitialization,
                                com::sun::star::lang::XServiceInfo,
                                com::sun::star::java::XJavaVM,
                                com::sun::star::java::XJavaThreadRegister_11,
                                com::sun::star::container::XContainerListener >
JavaVirtualMachine_Impl;

class JavaVirtualMachine: private osl::Mutex, public JavaVirtualMachine_Impl
{
public:
    explicit JavaVirtualMachine(
        com::sun::star::uno::Reference<
            com::sun::star::uno::XComponentContext > const & rContext);

    // XInitialization
    virtual void SAL_CALL
    initialize(com::sun::star::uno::Sequence< com::sun::star::uno::Any > const &
                   rArguments)
        throw (com::sun::star::uno::Exception);

    // XServiceInfo
    virtual rtl::OUString SAL_CALL getImplementationName()
        throw (com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL
    supportsService(rtl::OUString const & rServiceName)
        throw (com::sun::star::uno::RuntimeException);

    virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
    getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);

    // XJavaVM
    virtual com::sun::star::uno::Any SAL_CALL
    getJavaVM(com::sun::star::uno::Sequence< sal_Int8 > const & rProcessId)
        throw (com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL isVMStarted()
        throw (com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL isVMEnabled()
        throw (com::sun::star::uno::RuntimeException);

    // XJavaThreadRegister_11
    virtual sal_Bool SAL_CALL isThreadAttached()
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL registerThread()
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL revokeThread()
        throw (com::sun::star::uno::RuntimeException);

    // XContainerListener
    virtual void SAL_CALL
    disposing(com::sun::star::lang::EventObject const & rSource)
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL
    elementInserted(com::sun::star::container::ContainerEvent const & rEvent)
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL
    elementRemoved(com::sun::star::container::ContainerEvent const & rEvent)
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL
    elementReplaced(com::sun::star::container::ContainerEvent const & rEvent)
        throw (com::sun::star::uno::RuntimeException);

private:
    JavaVirtualMachine(JavaVirtualMachine &); // not implemented
    void operator =(JavaVirtualMachine); // not implemented

    virtual ~JavaVirtualMachine();

    virtual void SAL_CALL disposing();

    JavaVM * createJavaVM(JVM const & jvm, JNIEnv ** pMainThreadEnv);
        // throws com::sun::star::uno::RuntimeException

    void registerConfigChangesListener();

    void setINetSettingsInVM(bool set_reset);

    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
        m_xContext;

    // the following are controlled by the 'this' mutex:
    bool m_bDisposed;
    rtl::Reference< jvmaccess::VirtualMachine > m_xVirtualMachine;
    JavaVM * m_pJavaVm;
        // stored as an instance member for backwards compatibility in getJavaVM
    bool m_bDontCreateJvm;
        // If the first creation of Java failed and this flag is set then the
        // next call to getJavaVM throws a RuntimException.  This is useful when
        // the second attempt to create Java might cause a crash.
    com::sun::star::uno::Reference< com::sun::star::container::XContainer >
        m_xInetConfiguration;
    com::sun::star::uno::Reference< com::sun::star::container::XContainer >
        m_xJavaConfiguration; // for Java settings
    osl::Module m_aJavaLib;

    osl::ThreadData m_aAttachGuards;
};

}

#endif // INCLUDED_STOC_JAVAVM_JAVAVM_HXX
<commit_msg>INTEGRATION: CWS jl6 (1.3.96); FILE MERGED 2004/02/19 09:47:18 jl 1.3.96.1: #1150008#<commit_after>/*************************************************************************
 *
 *  $RCSfile: javavm.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2004-06-01 09:03:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source 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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#if !defined INCLUDED_STOC_JAVAVM_JAVAVM_HXX
#define INCLUDED_STOC_JAVAVM_JAVAVM_HXX

#include "jvmargs.hxx"

#include "com/sun/star/container/XContainerListener.hpp"
#include "com/sun/star/lang/XInitialization.hpp"
#include "com/sun/star/java/XJavaThreadRegister_11.hpp"
#include "com/sun/star/java/XJavaVM.hpp"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "cppuhelper/compbase5.hxx"
#include "osl/module.hxx"
#include "osl/thread.hxx"
#include "rtl/ref.hxx"

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace container { class XContainer; }
    namespace uno { class XComponentContext; }
} } }
namespace jvmaccess { class VirtualMachine; }

namespace stoc_javavm {

bool configureJava(const com::sun::star::uno::Reference<
                   com::sun::star::uno::XComponentContext>& xContext);
// The MS compiler needs a typedef here, so the JavaVirtualMachine ctor can call
// its base class ctor:
typedef
cppu::WeakComponentImplHelper5< com::sun::star::lang::XInitialization,
                                com::sun::star::lang::XServiceInfo,
                                com::sun::star::java::XJavaVM,
                                com::sun::star::java::XJavaThreadRegister_11,
                                com::sun::star::container::XContainerListener >
JavaVirtualMachine_Impl;

class JavaVirtualMachine: private osl::Mutex, public JavaVirtualMachine_Impl
{
public:
    explicit JavaVirtualMachine(
        com::sun::star::uno::Reference<
            com::sun::star::uno::XComponentContext > const & rContext);

    // XInitialization
    virtual void SAL_CALL
    initialize(com::sun::star::uno::Sequence< com::sun::star::uno::Any > const &
                   rArguments)
        throw (com::sun::star::uno::Exception);

    // XServiceInfo
    virtual rtl::OUString SAL_CALL getImplementationName()
        throw (com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL
    supportsService(rtl::OUString const & rServiceName)
        throw (com::sun::star::uno::RuntimeException);

    virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
    getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);

    // XJavaVM
    virtual com::sun::star::uno::Any SAL_CALL
    getJavaVM(com::sun::star::uno::Sequence< sal_Int8 > const & rProcessId)
        throw (com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL isVMStarted()
        throw (com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL isVMEnabled()
        throw (com::sun::star::uno::RuntimeException);

    // XJavaThreadRegister_11
    virtual sal_Bool SAL_CALL isThreadAttached()
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL registerThread()
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL revokeThread()
        throw (com::sun::star::uno::RuntimeException);

    // XContainerListener
    virtual void SAL_CALL
    disposing(com::sun::star::lang::EventObject const & rSource)
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL
    elementInserted(com::sun::star::container::ContainerEvent const & rEvent)
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL
    elementRemoved(com::sun::star::container::ContainerEvent const & rEvent)
        throw (com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL
    elementReplaced(com::sun::star::container::ContainerEvent const & rEvent)
        throw (com::sun::star::uno::RuntimeException);

private:
    JavaVirtualMachine(JavaVirtualMachine &); // not implemented
    void operator =(JavaVirtualMachine); // not implemented

    virtual ~JavaVirtualMachine();

    virtual void SAL_CALL disposing();

    JavaVM * createJavaVM(JVM const & jvm, JNIEnv ** pMainThreadEnv);
        // throws com::sun::star::uno::RuntimeException

    void registerConfigChangesListener();

    void setINetSettingsInVM(bool set_reset);

    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
        m_xContext;

    // the following are controlled by the 'this' mutex:
    bool m_bDisposed;
    rtl::Reference< jvmaccess::VirtualMachine > m_xVirtualMachine;
    JavaVM * m_pJavaVm;
        // stored as an instance member for backwards compatibility in getJavaVM
    bool m_bDontCreateJvm;
        // If the first creation of Java failed and this flag is set then the
        // next call to getJavaVM throws a RuntimException.  This is useful when
        // the second attempt to create Java might cause a crash.
    com::sun::star::uno::Reference< com::sun::star::container::XContainer >
        m_xInetConfiguration;
    com::sun::star::uno::Reference< com::sun::star::container::XContainer >
        m_xJavaConfiguration; // for Java settings
    osl::Module m_aJavaLib;

    osl::ThreadData m_aAttachGuards;
};

}

#endif // INCLUDED_STOC_JAVAVM_JAVAVM_HXX
<|endoftext|>