<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Antonio Recuero, Milad Rakhsha
// =============================================================================
//
// Unit test for EAS Brick Element
//
// This unit test checks the dynamics of a beam made up of 10 brick elemnts.
// It serves to validate the elastic, isotropic, large deformation internal forces,
// the element inertia, and this element'sgravity forces.
//
// This element is a regular 8-noded trilinear brick element with enhanced assumed
// strain that alleviates locking. More information on the validation of this element
// may be found in Chrono's documentation. This simulation excites the beam by applying
// the sudden action of a gravity field.
// =============================================================================

#include "chrono/core/ChFileutils.h"
#include "chrono/physics/ChSystem.h"
#include "chrono/lcp/ChLcpIterativeMINRES.h"
#include "chrono/utils/ChUtilsInputOutput.h"
#include "chrono_fea/ChElementSpring.h"
#include "chrono_fea/ChElementBrick.h"
#include "chrono_fea/ChElementBar.h"
#include "chrono_fea/ChLinkPointFrame.h"
#include "chrono_fea/ChLinkDirFrame.h"
#include "chrono_fea/ChVisualizationFEAmesh.h"

using namespace chrono;
using namespace fea;

const double step_size = 1e-3;  // Step size
double sim_time = 2;            // Simulation time for generation of reference file
double precision = 1e-6;        // Precision value used to assess results
double sim_time_UT = 0.1;       // Simulation time for unit test 0.05

int main(int argc, char* argv[]) {
    bool output = 0;  // Determines whether it tests (0) or generates golden file (1)

    ChMatrixDynamic<> FileInputMat(2000, 2);
    if (output) {
        GetLog() << "Output file: ../TEST_Brick/UT_EASBrickIso_Grav.txt\n";
    } else {
        // Utils to open/read files: Load reference solution ("golden") file
        std::string EASBrick_val_file = GetChronoDataPath() + "testing/" + "UT_EASBrickIso_Grav.txt";
        std::ifstream fileMid(EASBrick_val_file);

        if (!fileMid.is_open()) {
            fileMid.open(EASBrick_val_file);
        }
        if (!fileMid) {
            std::cout << "Cannot open validation file.\n";
            exit(1);
        }
        for (int x = 0; x < 2000; x++) {
            fileMid >> FileInputMat[x][0] >> FileInputMat[x][1];
        }
        fileMid.close();
        GetLog() << "Running in unit test mode.\n";
    }
    // Create the physical system

    ChSystem my_system;

    ChSharedPtr<ChMesh> my_mesh(new ChMesh);

    // Dimensions of the plate
    double plate_lenght_x = 1;
    double plate_lenght_y = 0.1;
    double plate_lenght_z = 0.01;  // small thickness
    // Specification of the mesh
    int numDiv_x = 10;  // 10 elements along the length of the beam
    int numDiv_y = 1;
    int numDiv_z = 1;
    int N_x = numDiv_x + 1;
    int N_y = numDiv_y + 1;
    int N_z = numDiv_z + 1;
    // Number of elements in the z direction is considered as 1
    int TotalNumElements = numDiv_x;
    int TotalNumNodes = (numDiv_x + 1) * 4;  // 4 nodes per brick face
    // For uniform mesh
    double dx = plate_lenght_x / numDiv_x;
    double dy = plate_lenght_y / numDiv_y;
    double dz = plate_lenght_z / numDiv_z;
    int MaxMNUM = 1;
    int MTYPE = 1;
    int MaxLayNum = 1;
    ChMatrixDynamic<double> COORDFlex(TotalNumNodes, 3);
    ChMatrixDynamic<double> VELCYFlex(TotalNumNodes, 3);
    ChMatrixDynamic<int> NumNodes(TotalNumElements, 8);
    ChMatrixDynamic<int> LayNum(TotalNumElements, 1);
    ChMatrixDynamic<int> NDR(TotalNumNodes, 3);
    ChMatrixDynamic<double> ElemLengthXY(TotalNumElements, 3);
    ChMatrixNM<double, 10, 12> MPROP;

    //!------------ Material Data-----------------

    for (int i = 0; i < MaxMNUM; i++) {
        MPROP(i, 0) = 500;      // Density [kg/m3]
        MPROP(i, 1) = 2.1E+07;  // E (Pa)
        MPROP(i, 2) = 0.3;      // nu
    }

    ChSharedPtr<ChContinuumElastic> mmaterial(new ChContinuumElastic);
    mmaterial->Set_RayleighDampingK(0.0);
    mmaterial->Set_RayleighDampingM(0.0);
    mmaterial->Set_density(MPROP(0, 0));
    mmaterial->Set_E(MPROP(0, 1));
    mmaterial->Set_G(MPROP(0, 1) / (2 + 2 * MPROP(0, 2)));
    mmaterial->Set_v(MPROP(0, 2));

    //!--------------- Element data--------------------

    for (int i = 0; i < TotalNumElements; i++) {
        // All the elements belong to the same layer, e.g layer number 1.
        LayNum(i, 0) = 1;

        NumNodes(i, 0) = i;
        NumNodes(i, 1) = i + 1;
        NumNodes(i, 2) = i + 1 + N_x;
        NumNodes(i, 3) = i + N_x;
        NumNodes(i, 4) = i + 2 * N_x;
        NumNodes(i, 5) = i + 2 * N_x + 1;
        NumNodes(i, 6) = i + 3 * N_x + 1;
        NumNodes(i, 7) = i + 3 * N_x;  // Numbering of nodes

        ElemLengthXY(i, 0) = dx;
        ElemLengthXY(i, 1) = dy;
        ElemLengthXY(i, 2) = dz;

        if (MaxLayNum < LayNum(i, 0)) {
            MaxLayNum = LayNum(i, 0);
        }
    }

    //!--------- Constraints and initial coordinates/velocities

    for (int i = 0; i < TotalNumNodes; i++) {
        // Constrain clamped nodes. Assigns (1) if constrained, (0) otherwise
        NDR(i, 0) = (i % N_x == 0) ? 1 : 0;
        NDR(i, 1) = (i % N_x == 0) ? 1 : 0;
        NDR(i, 2) = (i % N_x == 0) ? 1 : 0;

        // Coordinates
        COORDFlex(i, 0) = (i % (N_x)) * dx;
        if ((i / N_x + 1) % 2 == 0) {
            COORDFlex(i, 1) = dy;
        } else {
            COORDFlex(i, 1) = 0.0;
        };
        COORDFlex(i, 2) = (i) / ((N_x)*2) * dz;

        // Velocities
        VELCYFlex(i, 0) = 0;
        VELCYFlex(i, 1) = 0;
        VELCYFlex(i, 2) = 0;
    }

    // Adding the nodes to the mesh
    int i = 0;
    while (i < TotalNumNodes) {
        ChSharedPtr<ChNodeFEAxyz> node(new ChNodeFEAxyz(ChVector<>(COORDFlex(i, 0), COORDFlex(i, 1), COORDFlex(i, 2))));
        node->SetMass(0.0);
        my_mesh->AddNode(node);
        if (NDR(i, 0) == 1 && NDR(i, 1) == 1 && NDR(i, 2) == 1) {
            node->SetFixed(true);
        }
        i++;
    }

    // Create a node at the tip by dynamic casting
    ChSharedPtr<ChNodeFEAxyz> nodetip(my_mesh->GetNode(TotalNumNodes - 1).DynamicCastTo<ChNodeFEAxyz>());

    int elemcount = 0;
    while (elemcount < TotalNumElements) {
        ChSharedPtr<ChElementBrick> element(new ChElementBrick);
        ChMatrixNM<double, 3, 1> InertFlexVec;  // Read element length, used in ChElementBrick
        InertFlexVec.Reset();
        InertFlexVec(0, 0) = ElemLengthXY(elemcount, 0);
        InertFlexVec(1, 0) = ElemLengthXY(elemcount, 1);
        InertFlexVec(2, 0) = ElemLengthXY(elemcount, 2);
        element->SetInertFlexVec(InertFlexVec);
        // Note we change the order of the nodes to comply with the arrangement of shape functions
        element->SetNodes(my_mesh->GetNode(NumNodes(elemcount, 0)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 1)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 3)).DynamicCastTo<ChNodeFEAxyz>(),  //
                          my_mesh->GetNode(NumNodes(elemcount, 2)).DynamicCastTo<ChNodeFEAxyz>(),  //
                          my_mesh->GetNode(NumNodes(elemcount, 4)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 5)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 7)).DynamicCastTo<ChNodeFEAxyz>(),   //
                          my_mesh->GetNode(NumNodes(elemcount, 6)).DynamicCastTo<ChNodeFEAxyz>());  //

        element->SetMaterial(mmaterial);
        element->SetElemNum(elemcount);
        element->SetGravityOn(true);      // Turn gravity on/off from within the element
        element->SetMooneyRivlin(false);  // Turn on/off Mooney Rivlin (Linear Isotropic by default)
        // element->SetMRCoefficients(551584.0, 137896.0); // Set two coefficients for Mooney-Rivlin

        ChMatrixNM<double, 9, 1> stock_alpha_EAS;
        stock_alpha_EAS.Reset();
        element->SetStockAlpha(stock_alpha_EAS(0, 0), stock_alpha_EAS(1, 0), stock_alpha_EAS(2, 0),
                               stock_alpha_EAS(3, 0), stock_alpha_EAS(4, 0), stock_alpha_EAS(5, 0),
                               stock_alpha_EAS(6, 0), stock_alpha_EAS(7, 0), stock_alpha_EAS(8, 0));
        my_mesh->AddElement(element);
        elemcount++;
    }

    // This is mandatory
    my_mesh->SetupInitial();
    // Deactivate automatic gravity in mesh
    my_mesh->SetAutomaticGravity(false);
    // Remember to add the mesh to the system!
    my_system.Add(my_mesh);

    // Perform a dynamic time integration:
    my_system.SetLcpSolverType(
        ChSystem::LCP_ITERATIVE_MINRES);  // <- NEEDED because other solvers can't handle stiffness matrices
    chrono::ChLcpIterativeMINRES* msolver = (chrono::ChLcpIterativeMINRES*)my_system.GetLcpSolverSpeed();
    msolver->SetDiagonalPreconditioning(true);
    my_system.SetIterLCPmaxItersSpeed(10000);
    my_system.SetTolForce(1e-09);

    my_system.SetIntegrationType(ChSystem::INT_HHT);
    ChSharedPtr<ChTimestepperHHT> mystepper = my_system.GetTimestepper().DynamicCastTo<ChTimestepperHHT>();
    mystepper->SetAlpha(-0.01);
    mystepper->SetMaxiters(10000);
    mystepper->SetTolerance(1e-09);
    mystepper->SetMode(ChTimestepperHHT::POSITION);
    mystepper->SetScaling(true);

    // Simulation loop
    if (output) {
        // Create output directory (if it does not already exist).
        if (ChFileutils::MakeDirectory("../TEST_Brick") < 0) {
            GetLog() << "Error creating directory ../TEST_Brick\n";
            return 1;
        }
        // Initialize the output stream and set precision.
        utils::CSV_writer out("\t");
        out.stream().setf(std::ios::scientific | std::ios::showpos);
        out.stream().precision(7);
        int Iterations = 0;
        // Simulate to final time, while saving position of tip node.
        while (my_system.GetChTime() < sim_time) {
            my_system.DoStepDynamics(step_size);
            Iterations += mystepper->GetNumIterations();
            out << my_system.GetChTime() << nodetip->GetPos().z << std::endl;
            GetLog() << "time = " << my_system.GetChTime() << "\t" << nodetip->GetPos().z << "\t"
                     << nodetip->GetForce().z << "\t" << Iterations << "\n";
        }
        // Write results to output file.
        out.write_to_file("../TEST_Brick/UT_EASBrickIso_Grav.txt.txt");
    } else {
        // Initialize total number of iterations and timer.
        int Iterations = 0;
        double start = std::clock();
        int stepNo = 0;
        double AbsVal = 0.0;
        // Simulate to final time, while accumulating number of iterations.
        while (my_system.GetChTime() < sim_time_UT) {
            my_system.DoStepDynamics(step_size);
            AbsVal = abs(nodetip->GetPos().z - FileInputMat[stepNo][1]);
            GetLog() << "time = " << my_system.GetChTime() << "\t" << nodetip->GetPos().z << "\n";
            if (AbsVal > precision) {
                std::cout << "Unit test check failed \n";
                return 1;
            }
            stepNo++;
            Iterations += mystepper->GetNumIterations();
        }
        // Report run time and total number of iterations.
        double duration = (std::clock() - start) / (double)CLOCKS_PER_SEC;
        GetLog() << "Computation Time: " << duration << "   Number of iterations: " << Iterations << "\n";
        std::cout << "Unit test check succeeded \n";
    }

    return 0;
}
<commit_msg>Reduce simulation time tested in test_EASBrickIso_Grav.cpp<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Antonio Recuero, Milad Rakhsha
// =============================================================================
//
// Unit test for EAS Brick Element
//
// This unit test checks the dynamics of a beam made up of 10 brick elemnts.
// It serves to validate the elastic, isotropic, large deformation internal forces,
// the element inertia, and this element'sgravity forces.
//
// This element is a regular 8-noded trilinear brick element with enhanced assumed
// strain that alleviates locking. More information on the validation of this element
// may be found in Chrono's documentation. This simulation excites the beam by applying
// the sudden action of a gravity field.
// =============================================================================

#include "chrono/core/ChFileutils.h"
#include "chrono/physics/ChSystem.h"
#include "chrono/lcp/ChLcpIterativeMINRES.h"
#include "chrono/utils/ChUtilsInputOutput.h"
#include "chrono_fea/ChElementSpring.h"
#include "chrono_fea/ChElementBrick.h"
#include "chrono_fea/ChElementBar.h"
#include "chrono_fea/ChLinkPointFrame.h"
#include "chrono_fea/ChLinkDirFrame.h"
#include "chrono_fea/ChVisualizationFEAmesh.h"

using namespace chrono;
using namespace fea;

const double step_size = 1e-3;  // Step size
double sim_time = 2;            // Simulation time for generation of reference file
double precision = 1e-6;        // Precision value used to assess results
double sim_time_UT = 0.05;       // Simulation time for unit test 0.05

int main(int argc, char* argv[]) {
    bool output = 0;  // Determines whether it tests (0) or generates golden file (1)

    ChMatrixDynamic<> FileInputMat(2000, 2);
    if (output) {
        GetLog() << "Output file: ../TEST_Brick/UT_EASBrickIso_Grav.txt\n";
    } else {
        // Utils to open/read files: Load reference solution ("golden") file
        std::string EASBrick_val_file = GetChronoDataPath() + "testing/" + "UT_EASBrickIso_Grav.txt";
        std::ifstream fileMid(EASBrick_val_file);

        if (!fileMid.is_open()) {
            fileMid.open(EASBrick_val_file);
        }
        if (!fileMid) {
            std::cout << "Cannot open validation file.\n";
            exit(1);
        }
        for (int x = 0; x < 2000; x++) {
            fileMid >> FileInputMat[x][0] >> FileInputMat[x][1];
        }
        fileMid.close();
        GetLog() << "Running in unit test mode.\n";
    }
    // Create the physical system

    ChSystem my_system;

    ChSharedPtr<ChMesh> my_mesh(new ChMesh);

    // Dimensions of the plate
    double plate_lenght_x = 1;
    double plate_lenght_y = 0.1;
    double plate_lenght_z = 0.01;  // small thickness
    // Specification of the mesh
    int numDiv_x = 10;  // 10 elements along the length of the beam
    int numDiv_y = 1;
    int numDiv_z = 1;
    int N_x = numDiv_x + 1;
    int N_y = numDiv_y + 1;
    int N_z = numDiv_z + 1;
    // Number of elements in the z direction is considered as 1
    int TotalNumElements = numDiv_x;
    int TotalNumNodes = (numDiv_x + 1) * 4;  // 4 nodes per brick face
    // For uniform mesh
    double dx = plate_lenght_x / numDiv_x;
    double dy = plate_lenght_y / numDiv_y;
    double dz = plate_lenght_z / numDiv_z;
    int MaxMNUM = 1;
    int MTYPE = 1;
    int MaxLayNum = 1;
    ChMatrixDynamic<double> COORDFlex(TotalNumNodes, 3);
    ChMatrixDynamic<double> VELCYFlex(TotalNumNodes, 3);
    ChMatrixDynamic<int> NumNodes(TotalNumElements, 8);
    ChMatrixDynamic<int> LayNum(TotalNumElements, 1);
    ChMatrixDynamic<int> NDR(TotalNumNodes, 3);
    ChMatrixDynamic<double> ElemLengthXY(TotalNumElements, 3);
    ChMatrixNM<double, 10, 12> MPROP;

    //!------------ Material Data-----------------

    for (int i = 0; i < MaxMNUM; i++) {
        MPROP(i, 0) = 500;      // Density [kg/m3]
        MPROP(i, 1) = 2.1E+07;  // E (Pa)
        MPROP(i, 2) = 0.3;      // nu
    }

    ChSharedPtr<ChContinuumElastic> mmaterial(new ChContinuumElastic);
    mmaterial->Set_RayleighDampingK(0.0);
    mmaterial->Set_RayleighDampingM(0.0);
    mmaterial->Set_density(MPROP(0, 0));
    mmaterial->Set_E(MPROP(0, 1));
    mmaterial->Set_G(MPROP(0, 1) / (2 + 2 * MPROP(0, 2)));
    mmaterial->Set_v(MPROP(0, 2));

    //!--------------- Element data--------------------

    for (int i = 0; i < TotalNumElements; i++) {
        // All the elements belong to the same layer, e.g layer number 1.
        LayNum(i, 0) = 1;

        NumNodes(i, 0) = i;
        NumNodes(i, 1) = i + 1;
        NumNodes(i, 2) = i + 1 + N_x;
        NumNodes(i, 3) = i + N_x;
        NumNodes(i, 4) = i + 2 * N_x;
        NumNodes(i, 5) = i + 2 * N_x + 1;
        NumNodes(i, 6) = i + 3 * N_x + 1;
        NumNodes(i, 7) = i + 3 * N_x;  // Numbering of nodes

        ElemLengthXY(i, 0) = dx;
        ElemLengthXY(i, 1) = dy;
        ElemLengthXY(i, 2) = dz;

        if (MaxLayNum < LayNum(i, 0)) {
            MaxLayNum = LayNum(i, 0);
        }
    }

    //!--------- Constraints and initial coordinates/velocities

    for (int i = 0; i < TotalNumNodes; i++) {
        // Constrain clamped nodes. Assigns (1) if constrained, (0) otherwise
        NDR(i, 0) = (i % N_x == 0) ? 1 : 0;
        NDR(i, 1) = (i % N_x == 0) ? 1 : 0;
        NDR(i, 2) = (i % N_x == 0) ? 1 : 0;

        // Coordinates
        COORDFlex(i, 0) = (i % (N_x)) * dx;
        if ((i / N_x + 1) % 2 == 0) {
            COORDFlex(i, 1) = dy;
        } else {
            COORDFlex(i, 1) = 0.0;
        };
        COORDFlex(i, 2) = (i) / ((N_x)*2) * dz;

        // Velocities
        VELCYFlex(i, 0) = 0;
        VELCYFlex(i, 1) = 0;
        VELCYFlex(i, 2) = 0;
    }

    // Adding the nodes to the mesh
    int i = 0;
    while (i < TotalNumNodes) {
        ChSharedPtr<ChNodeFEAxyz> node(new ChNodeFEAxyz(ChVector<>(COORDFlex(i, 0), COORDFlex(i, 1), COORDFlex(i, 2))));
        node->SetMass(0.0);
        my_mesh->AddNode(node);
        if (NDR(i, 0) == 1 && NDR(i, 1) == 1 && NDR(i, 2) == 1) {
            node->SetFixed(true);
        }
        i++;
    }

    // Create a node at the tip by dynamic casting
    ChSharedPtr<ChNodeFEAxyz> nodetip(my_mesh->GetNode(TotalNumNodes - 1).DynamicCastTo<ChNodeFEAxyz>());

    int elemcount = 0;
    while (elemcount < TotalNumElements) {
        ChSharedPtr<ChElementBrick> element(new ChElementBrick);
        ChMatrixNM<double, 3, 1> InertFlexVec;  // Read element length, used in ChElementBrick
        InertFlexVec.Reset();
        InertFlexVec(0, 0) = ElemLengthXY(elemcount, 0);
        InertFlexVec(1, 0) = ElemLengthXY(elemcount, 1);
        InertFlexVec(2, 0) = ElemLengthXY(elemcount, 2);
        element->SetInertFlexVec(InertFlexVec);
        // Note we change the order of the nodes to comply with the arrangement of shape functions
        element->SetNodes(my_mesh->GetNode(NumNodes(elemcount, 0)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 1)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 3)).DynamicCastTo<ChNodeFEAxyz>(),  //
                          my_mesh->GetNode(NumNodes(elemcount, 2)).DynamicCastTo<ChNodeFEAxyz>(),  //
                          my_mesh->GetNode(NumNodes(elemcount, 4)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 5)).DynamicCastTo<ChNodeFEAxyz>(),
                          my_mesh->GetNode(NumNodes(elemcount, 7)).DynamicCastTo<ChNodeFEAxyz>(),   //
                          my_mesh->GetNode(NumNodes(elemcount, 6)).DynamicCastTo<ChNodeFEAxyz>());  //

        element->SetMaterial(mmaterial);
        element->SetElemNum(elemcount);
        element->SetGravityOn(true);      // Turn gravity on/off from within the element
        element->SetMooneyRivlin(false);  // Turn on/off Mooney Rivlin (Linear Isotropic by default)
        // element->SetMRCoefficients(551584.0, 137896.0); // Set two coefficients for Mooney-Rivlin

        ChMatrixNM<double, 9, 1> stock_alpha_EAS;
        stock_alpha_EAS.Reset();
        element->SetStockAlpha(stock_alpha_EAS(0, 0), stock_alpha_EAS(1, 0), stock_alpha_EAS(2, 0),
                               stock_alpha_EAS(3, 0), stock_alpha_EAS(4, 0), stock_alpha_EAS(5, 0),
                               stock_alpha_EAS(6, 0), stock_alpha_EAS(7, 0), stock_alpha_EAS(8, 0));
        my_mesh->AddElement(element);
        elemcount++;
    }

    // This is mandatory
    my_mesh->SetupInitial();
    // Deactivate automatic gravity in mesh
    my_mesh->SetAutomaticGravity(false);
    // Remember to add the mesh to the system!
    my_system.Add(my_mesh);

    // Perform a dynamic time integration:
    my_system.SetLcpSolverType(
        ChSystem::LCP_ITERATIVE_MINRES);  // <- NEEDED because other solvers can't handle stiffness matrices
    chrono::ChLcpIterativeMINRES* msolver = (chrono::ChLcpIterativeMINRES*)my_system.GetLcpSolverSpeed();
    msolver->SetDiagonalPreconditioning(true);
    my_system.SetIterLCPmaxItersSpeed(10000);
    my_system.SetTolForce(1e-09);

    my_system.SetIntegrationType(ChSystem::INT_HHT);
    ChSharedPtr<ChTimestepperHHT> mystepper = my_system.GetTimestepper().DynamicCastTo<ChTimestepperHHT>();
    mystepper->SetAlpha(-0.01);
    mystepper->SetMaxiters(10000);
    mystepper->SetTolerance(1e-09);
    mystepper->SetMode(ChTimestepperHHT::POSITION);
    mystepper->SetScaling(true);

    // Simulation loop
    if (output) {
        // Create output directory (if it does not already exist).
        if (ChFileutils::MakeDirectory("../TEST_Brick") < 0) {
            GetLog() << "Error creating directory ../TEST_Brick\n";
            return 1;
        }
        // Initialize the output stream and set precision.
        utils::CSV_writer out("\t");
        out.stream().setf(std::ios::scientific | std::ios::showpos);
        out.stream().precision(7);
        int Iterations = 0;
        // Simulate to final time, while saving position of tip node.
        while (my_system.GetChTime() < sim_time) {
            my_system.DoStepDynamics(step_size);
            Iterations += mystepper->GetNumIterations();
            out << my_system.GetChTime() << nodetip->GetPos().z << std::endl;
            GetLog() << "time = " << my_system.GetChTime() << "\t" << nodetip->GetPos().z << "\t"
                     << nodetip->GetForce().z << "\t" << Iterations << "\n";
        }
        // Write results to output file.
        out.write_to_file("../TEST_Brick/UT_EASBrickIso_Grav.txt.txt");
    } else {
        // Initialize total number of iterations and timer.
        int Iterations = 0;
        double start = std::clock();
        int stepNo = 0;
        double AbsVal = 0.0;
        // Simulate to final time, while accumulating number of iterations.
        while (my_system.GetChTime() < sim_time_UT) {
            my_system.DoStepDynamics(step_size);
            AbsVal = abs(nodetip->GetPos().z - FileInputMat[stepNo][1]);
            GetLog() << "time = " << my_system.GetChTime() << "\t" << nodetip->GetPos().z << "\n";
            if (AbsVal > precision) {
                std::cout << "Unit test check failed \n";
                return 1;
            }
            stepNo++;
            Iterations += mystepper->GetNumIterations();
        }
        // Report run time and total number of iterations.
        double duration = (std::clock() - start) / (double)CLOCKS_PER_SEC;
        GetLog() << "Computation Time: " << duration << "   Number of iterations: " << Iterations << "\n";
        std::cout << "Unit test check succeeded \n";
    }

    return 0;
}
<|endoftext|>


<commit_before>// -*-Mode: C++;-*-
// $Id$

// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002-2007, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

// ----------------------------------------------------------------------
//
//   the implementation of evaluation tree nodes
//
// ----------------------------------------------------------------------

//************************ System Include Files ******************************

#include <iostream>
using std::endl;

#include <sstream>
#include <string>
#include <algorithm>

#include <cmath>

//************************* User Include Files *******************************

#include <include/general.h>

#include "Metric-AExpr.hpp"

#include <lib/support/NaN.h>
#include <lib/support/Trace.hpp>

//************************ Forward Declarations ******************************

#define AEXPR_DO_CHECK 0
#if (AEXPR_DO_CHECK)
# define AEXPR_CHECK(x) if (!isok(x)) { return c_FP_NAN_d; }
#else
# define AEXPR_CHECK(x)
#endif

//****************************************************************************

namespace Prof {

namespace Metric {

// ----------------------------------------------------------------------
// class AExpr
// ----------------------------------------------------------------------

std::string
AExpr::toString() const
{
  std::ostringstream os;
  dump(os);
  return os.str();
}

void
AExpr::dump_opands(std::ostream& os, AExpr** opands, int sz, const char* sep)
{
  for (int i = 0; i < sz; ++i) {
    opands[i]->dump(os);
    if (i < (sz - 1)) {
      os << sep;
    }
  }
}

// ----------------------------------------------------------------------
// class Const
// ----------------------------------------------------------------------

std::ostream&
Const::dump(std::ostream& os) const
{
  os << "(" << m_c << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Neg
// ----------------------------------------------------------------------

double
Neg::eval(const ScopeInfo* si) const
{
  double result = m_expr->eval(si);

  //IFTRACE << "neg=" << -result << endl;
  AEXPR_CHECK(result);
  return -result;
}

std::ostream&
Neg::dump(std::ostream& os) const
{
  os << "(-"; m_expr->dump(os); os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Var
// ----------------------------------------------------------------------

std::ostream&
Var::dump(std::ostream& os) const
{
  os << name;
  return os;
}

// ----------------------------------------------------------------------
// class Power
// ----------------------------------------------------------------------

Power::Power(AExpr* b, AExpr* e)
  : base(b), exponent(e)
{
}

Power::~Power()
{
  delete base;
  delete exponent;
}

double
Power::eval(const ScopeInfo* si) const
{
  double b = base->eval(si);
  double e = exponent->eval(si);
  double result = pow(b, e);

  //IFTRACE << "pow=" << pow(b, e) << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Power::dump(std::ostream& os) const
{
  os << "("; base->dump(os); os << "**"; exponent->dump(os); os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Divide
// ----------------------------------------------------------------------

Divide::Divide(AExpr* num, AExpr* denom)
  : numerator(num), denominator(denom)
{
}

Divide::~Divide()
{
  delete numerator;
  delete denominator;
}

double
Divide::eval(const ScopeInfo* si) const
{
  double n = numerator->eval(si);
  double d = denominator->eval(si);
  double result = n / d;

  //IFTRACE << "divident=" << n/d << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Divide::dump(std::ostream& os) const
{
  os << "(";
  numerator->dump(os);
  os << " / ";
  denominator->dump(os);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Minus
// ----------------------------------------------------------------------

Minus::Minus(AExpr* m, AExpr* s)
  : minuend(m), subtrahend(s)
{
  // if (minuend == NULL || subtrahend == NULL) { ... }
}

Minus::~Minus()
{
  delete minuend;
  delete subtrahend;
}

double
Minus::eval(const ScopeInfo* si) const
{
  double m = minuend->eval(si);
  double s = subtrahend->eval(si);
  double result = (m - s);

  //IFTRACE << "diff=" << m-s << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Minus::dump(std::ostream& os) const
{
  os << "("; minuend->dump(os); os << " - "; subtrahend->dump(os); os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Plus
// ----------------------------------------------------------------------

Plus::Plus(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Plus::~Plus()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Plus::eval(const ScopeInfo* si) const
{
  double result = eval_sum(si, m_opands, m_sz);

  //IFTRACE << "sum=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Plus::dump(std::ostream& os) const
{
  os << "(";
  dump_opands(os, m_opands, m_sz, " + ");
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Times
// ----------------------------------------------------------------------

Times::Times(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Times::~Times()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Times::eval(const ScopeInfo* si) const
{
  double result = 1.0;
  for (int i = 0; i < m_sz; ++i) {
    double x = m_opands[i]->eval(si);
    result *= x;
  }
  //IFTRACE << "result=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Times::dump(std::ostream& os) const
{
  os << "(";
  dump_opands(os, m_opands, m_sz, " * ");
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Max
// ----------------------------------------------------------------------

Max::Max(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Max::~Max()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Max::eval(const ScopeInfo* si) const
{
  double result = m_opands[0]->eval(si);
  for (int i = 1; i < m_sz; ++i) {
    double x = m_opands[i]->eval(si);
    result = std::max(result, x);
  }

  //IFTRACE << "max=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Max::dump(std::ostream& os) const
{
  os << "max(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Min
// ----------------------------------------------------------------------

Min::Min(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Min::~Min()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Min::eval(const ScopeInfo* si) const
{
  double result = m_opands[0]->eval(si);
  for (int i = 1; i < m_sz; ++i) {
    double x = m_opands[i]->eval(si);
    result = std::min(result, x);
  }

  //IFTRACE << "min=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Min::dump(std::ostream& os) const
{
  os << "min(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Mean
// ----------------------------------------------------------------------

Mean::Mean(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Mean::~Mean()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Mean::eval(const ScopeInfo* si) const
{
  double result = eval_mean(si, m_opands, m_sz);

  //IFTRACE << "mean=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Mean::dump(std::ostream& os) const
{
  os << "mean(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class StdDev
// ----------------------------------------------------------------------

StdDev::StdDev(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

StdDev::~StdDev()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
StdDev::eval(const ScopeInfo* si) const
{
  std::pair<double, double> v_m = eval_variance(si, m_opands, m_sz);
  double result = sqrt(v_m.first);

  //IFTRACE << "stddev=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
StdDev::dump(std::ostream& os) const
{
  os << "stddev(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class RStdDev
// ----------------------------------------------------------------------

RStdDev::RStdDev(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

RStdDev::~RStdDev()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
RStdDev::eval(const ScopeInfo* si) const{

  std::pair<double, double> v_m = eval_variance(si, m_opands, m_sz);
  double sdev = sqrt(v_m.first);
  double result = (sdev / v_m.second) * 100;

  //IFTRACE << "r-stddev=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
RStdDev::dump(std::ostream& os) const
{
  os << "r-stddev(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

//****************************************************************************

} // namespace Metric

} // namespace Prof
<commit_msg>Prof::Metric::RStdDev::eval: handle divide by 0<commit_after>// -*-Mode: C++;-*-
// $Id$

// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002-2007, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

// ----------------------------------------------------------------------
//
//   the implementation of evaluation tree nodes
//
// ----------------------------------------------------------------------

//************************ System Include Files ******************************

#include <iostream>
using std::endl;

#include <sstream>
#include <string>
#include <algorithm>

#include <cmath>

//************************* User Include Files *******************************

#include <include/general.h>

#include "Metric-AExpr.hpp"

#include <lib/support/NaN.h>
#include <lib/support/Trace.hpp>

//************************ Forward Declarations ******************************

#define AEXPR_DO_CHECK 0
#if (AEXPR_DO_CHECK)
# define AEXPR_CHECK(x) if (!isok(x)) { return c_FP_NAN_d; }
#else
# define AEXPR_CHECK(x)
#endif

static double epsilon = 0.000001;

//****************************************************************************

namespace Prof {

namespace Metric {

// ----------------------------------------------------------------------
// class AExpr
// ----------------------------------------------------------------------

std::string
AExpr::toString() const
{
  std::ostringstream os;
  dump(os);
  return os.str();
}

void
AExpr::dump_opands(std::ostream& os, AExpr** opands, int sz, const char* sep)
{
  for (int i = 0; i < sz; ++i) {
    opands[i]->dump(os);
    if (i < (sz - 1)) {
      os << sep;
    }
  }
}

// ----------------------------------------------------------------------
// class Const
// ----------------------------------------------------------------------

std::ostream&
Const::dump(std::ostream& os) const
{
  os << "(" << m_c << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Neg
// ----------------------------------------------------------------------

double
Neg::eval(const ScopeInfo* si) const
{
  double result = m_expr->eval(si);

  //IFTRACE << "neg=" << -result << endl;
  AEXPR_CHECK(result);
  return -result;
}

std::ostream&
Neg::dump(std::ostream& os) const
{
  os << "(-"; m_expr->dump(os); os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Var
// ----------------------------------------------------------------------

std::ostream&
Var::dump(std::ostream& os) const
{
  os << name;
  return os;
}

// ----------------------------------------------------------------------
// class Power
// ----------------------------------------------------------------------

Power::Power(AExpr* b, AExpr* e)
  : base(b), exponent(e)
{
}

Power::~Power()
{
  delete base;
  delete exponent;
}

double
Power::eval(const ScopeInfo* si) const
{
  double b = base->eval(si);
  double e = exponent->eval(si);
  double result = pow(b, e);

  //IFTRACE << "pow=" << pow(b, e) << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Power::dump(std::ostream& os) const
{
  os << "("; base->dump(os); os << "**"; exponent->dump(os); os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Divide
// ----------------------------------------------------------------------

Divide::Divide(AExpr* num, AExpr* denom)
  : numerator(num), denominator(denom)
{
}

Divide::~Divide()
{
  delete numerator;
  delete denominator;
}

double
Divide::eval(const ScopeInfo* si) const
{
  double n = numerator->eval(si);
  double d = denominator->eval(si);
  double result = n / d;

  //IFTRACE << "divident=" << n/d << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Divide::dump(std::ostream& os) const
{
  os << "(";
  numerator->dump(os);
  os << " / ";
  denominator->dump(os);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Minus
// ----------------------------------------------------------------------

Minus::Minus(AExpr* m, AExpr* s)
  : minuend(m), subtrahend(s)
{
  // if (minuend == NULL || subtrahend == NULL) { ... }
}

Minus::~Minus()
{
  delete minuend;
  delete subtrahend;
}

double
Minus::eval(const ScopeInfo* si) const
{
  double m = minuend->eval(si);
  double s = subtrahend->eval(si);
  double result = (m - s);

  //IFTRACE << "diff=" << m-s << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Minus::dump(std::ostream& os) const
{
  os << "("; minuend->dump(os); os << " - "; subtrahend->dump(os); os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Plus
// ----------------------------------------------------------------------

Plus::Plus(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Plus::~Plus()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Plus::eval(const ScopeInfo* si) const
{
  double result = eval_sum(si, m_opands, m_sz);

  //IFTRACE << "sum=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Plus::dump(std::ostream& os) const
{
  os << "(";
  dump_opands(os, m_opands, m_sz, " + ");
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Times
// ----------------------------------------------------------------------

Times::Times(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Times::~Times()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Times::eval(const ScopeInfo* si) const
{
  double result = 1.0;
  for (int i = 0; i < m_sz; ++i) {
    double x = m_opands[i]->eval(si);
    result *= x;
  }
  //IFTRACE << "result=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Times::dump(std::ostream& os) const
{
  os << "(";
  dump_opands(os, m_opands, m_sz, " * ");
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Max
// ----------------------------------------------------------------------

Max::Max(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Max::~Max()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Max::eval(const ScopeInfo* si) const
{
  double result = m_opands[0]->eval(si);
  for (int i = 1; i < m_sz; ++i) {
    double x = m_opands[i]->eval(si);
    result = std::max(result, x);
  }

  //IFTRACE << "max=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Max::dump(std::ostream& os) const
{
  os << "max(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Min
// ----------------------------------------------------------------------

Min::Min(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Min::~Min()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Min::eval(const ScopeInfo* si) const
{
  double result = m_opands[0]->eval(si);
  for (int i = 1; i < m_sz; ++i) {
    double x = m_opands[i]->eval(si);
    result = std::min(result, x);
  }

  //IFTRACE << "min=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Min::dump(std::ostream& os) const
{
  os << "min(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class Mean
// ----------------------------------------------------------------------

Mean::Mean(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

Mean::~Mean()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
Mean::eval(const ScopeInfo* si) const
{
  double result = eval_mean(si, m_opands, m_sz);

  //IFTRACE << "mean=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
Mean::dump(std::ostream& os) const
{
  os << "mean(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class StdDev
// ----------------------------------------------------------------------

StdDev::StdDev(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

StdDev::~StdDev()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
StdDev::eval(const ScopeInfo* si) const
{
  std::pair<double, double> v_m = eval_variance(si, m_opands, m_sz);
  double result = sqrt(v_m.first);

  //IFTRACE << "stddev=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
StdDev::dump(std::ostream& os) const
{
  os << "stddev(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

// ----------------------------------------------------------------------
// class RStdDev
// ----------------------------------------------------------------------

RStdDev::RStdDev(AExpr** oprnds, int numOprnds)
  : m_opands(oprnds), m_sz(numOprnds)
{
}

RStdDev::~RStdDev()
{
  for (int i = 0; i < m_sz; ++i) {
    delete m_opands[i];
  }
  delete[] m_opands;
}

double
RStdDev::eval(const ScopeInfo* si) const{

  std::pair<double, double> v_m = eval_variance(si, m_opands, m_sz);
  double sdev = sqrt(v_m.first); // always non-negative
  double mean = v_m.second;
  double result = 0.0;
  if (mean > epsilon) {
    result = (sdev / mean) * 100;
  }

  //IFTRACE << "r-stddev=" << result << endl;
  AEXPR_CHECK(result);
  return result;
}

std::ostream&
RStdDev::dump(std::ostream& os) const
{
  os << "r-stddev(";
  dump_opands(os, m_opands, m_sz);
  os << ")";
  return os;
}

//****************************************************************************

} // namespace Metric

} // namespace Prof
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/core/ObjectFactory.h>
#include <SofaGeneralLoader/MeshSTLLoader.h>
#include <sofa/core/visual/VisualParams.h>

#include <sofa/helper/stl.hpp>
#include <iostream>
//#include <fstream> // we can't use iostream because the windows implementation gets confused by the mix of text and binary
#include <cstdio>
#include <sstream>
#include <string>

namespace sofa
{

namespace component
{

namespace loader
{

using namespace sofa::defaulttype;

SOFA_DECL_CLASS(MeshSTLLoader)

int MeshSTLLoaderClass = core::RegisterObject("Specific mesh loader for STL file format.")
        .add< MeshSTLLoader >()
        .addAlias("MeshStlLoader")
        ;

//Base VTK Loader
MeshSTLLoader::MeshSTLLoader() : MeshLoader()
    , _headerSize(initData(&_headerSize, 80u, "headerSize","Size of the header binary file (just before the number of facet)."))
    , _forceBinary(initData(&_forceBinary, false, "forceBinary","Force reading in binary mode. Even in first keyword of the file is solid."))
    , d_mergePositionUsingMap(initData(&d_mergePositionUsingMap, true, "mergePositionUsingMap","Since positions are duplicated in a STL, they have to be merged. Using a map to do so will temporarily duplicate memory but should be more efficient. Disable it if memory is really an issue."))
{
}

bool MeshSTLLoader::load()
{
    const char* filename = m_filename.getFullPath().c_str();

    std::ifstream file(filename);
    if (!file.good()) {
        msg_error() << "Cannot read file '" << m_filename;
        return false;
    }

    if( helper::stl::is_binary(file) || _forceBinary.getValue() ) {
        return this->readBinarySTL(filename);
    } else {
        return this->readSTL(file);
    }

}

bool MeshSTLLoader::readBinarySTL(const char *filename)
{
    dmsg_info() << "Reading binary STL file..." ;

    std::ifstream dataFile (filename, std::ios::in | std::ios::binary);

    helper::vector<sofa::defaulttype::Vector3>& my_positions = *(this->d_positions.beginWriteOnly());
    helper::vector<sofa::defaulttype::Vector3>& my_normals = *(this->d_normals.beginWriteOnly());
    helper::vector<Triangle >& my_triangles = *(this->d_triangles.beginWriteOnly());

    std::map< sofa::defaulttype::Vec3f, core::topology::Topology::index_type > my_map;
    core::topology::Topology::index_type positionCounter = 0;
    bool useMap = d_mergePositionUsingMap.getValue();

    // Skipping header file
    char buffer[256];
    dataFile.read(buffer, _headerSize.getValue());
//    sout << "Header binary file: "<< buffer << sendl;

    uint32_t nbrFacet;
    dataFile.read((char*)&nbrFacet, 4);

    my_triangles.resize( nbrFacet ); // exact size
    my_normals.resize( nbrFacet ); // exact size
    my_positions.reserve( nbrFacet * 3 ); // max size

#ifndef NDEBUG
    {
    // checking that the file is large enough to contain the given nb of facets
    // store current pos in file
    std::streampos pos = dataFile.tellg();
    // get length of file
    dataFile.seekg(0, std::ios::end);
    std::streampos length = dataFile.tellg();
    // restore pos in file
    dataFile.seekg(pos);
    // check for length
    assert( length >= _headerSize.getValue() + 4 + nbrFacet * (12 /*normal*/ + 3 * 12 /*points*/ + 2 /*attribute*/ ) );
    }
#endif

    // temporaries
    sofa::defaulttype::Vec3f vertex, normal;

    // Parsing facets
    for (uint32_t i = 0; i<nbrFacet; ++i)
    {
        Triangle& the_tri = my_triangles[i];

        // Normal:
        dataFile.read((char*)&normal[0], 4);
        dataFile.read((char*)&normal[1], 4);
        dataFile.read((char*)&normal[2], 4);
        my_normals[i] = normal;

        // Vertices:
        for (size_t j = 0; j<3; ++j)
        {
            dataFile.read((char*)&vertex[0], 4);
            dataFile.read((char*)&vertex[1], 4);
            dataFile.read((char*)&vertex[2], 4);

            if( useMap )
            {
                auto it = my_map.find( vertex );
                if( it == my_map.end() )
                {
                    the_tri[j] = positionCounter;
                    my_map[vertex] = positionCounter++;
                    my_positions.push_back(vertex);
                }
                else
                {
                    the_tri[j] = it->second;
                }
            }
            else
            {
                bool find = false;
                for (size_t k=0; k<my_positions.size(); ++k)
                    if ( (vertex[0] == my_positions[k][0]) && (vertex[1] == my_positions[k][1])  && (vertex[2] == my_positions[k][2]))
                    {
                        find = true;
                        the_tri[j] = static_cast<core::topology::Topology::PointID>(k);
                        break;
                    }

                if (!find)
                {
                    my_positions.push_back(vertex);
                    the_tri[j] = my_positions.size()-1;
                }
            }

        }

        // Attribute byte count
        uint16_t count;
        dataFile.read((char*)&count, 2);

        // Security: // checked once before reading in debug mode
//        position = dataFile.tellg();
//        if (position == length)
//            break;
    }

    this->d_positions.endEdit();
    this->d_triangles.endEdit();
    this->d_normals.endEdit();

    dmsg_info() << "done!" ;

    return true;
}

bool MeshSTLLoader::readSTL(std::ifstream& dataFile)
{
    dmsg_info() << "Reading STL file..." ;

    // Init
    std::string buffer;
    std::string name; // name of the solid, needed?

    helper::vector<sofa::defaulttype::Vector3>& my_positions = *(d_positions.beginEdit());
    helper::vector<sofa::defaulttype::Vector3>& my_normals = *(d_normals.beginEdit());
    helper::vector<Triangle >& my_triangles = *(d_triangles.beginEdit());

    std::map< sofa::defaulttype::Vec3f, core::topology::Topology::index_type > my_map;
    core::topology::Topology::index_type positionCounter = 0;
    bool useMap = d_mergePositionUsingMap.getValue();

    // get length of file:
    dataFile.seekg(0, std::ios::end);
    std::streampos length = dataFile.tellg();
    dataFile.seekg(0, std::ios::beg);

    // Reading header
    dataFile >> buffer >> name;

    Triangle the_tri;
    size_t cpt = 0;
    std::streampos position = 0;

    // Parsing facets
    while (position < length)
    {
        sofa::defaulttype::Vector3 normal, vertex;

        std::getline(dataFile, buffer);
        std::stringstream line;

        std::clog << line.str() << std::endl;

        std::string bufferWord;
        line >> bufferWord;

        if (bufferWord == "facet")
        {
            line >> bufferWord >> normal[0] >> normal[1] >> normal[2];
            my_normals.push_back(normal);
        }
        else if (bufferWord == "vertex")
        {
            line >> vertex[0] >> vertex[1] >> vertex[2];

            if( useMap )
            {
                auto it = my_map.find( vertex );
                if( it == my_map.end() )
                {
                    the_tri[cpt] = positionCounter;
                    my_map[vertex] = positionCounter++;
                    my_positions.push_back(vertex);
                }
                else
                {
                    the_tri[cpt] = it->second;
                }
            }
            else
            {

                bool find = false;
                for (size_t i=0; i<my_positions.size(); ++i)
                    if ( (vertex[0] == my_positions[i][0]) && (vertex[1] == my_positions[i][1])  && (vertex[2] == my_positions[i][2]))
                    {
                        find = true;
                        the_tri[cpt] = static_cast<core::topology::Topology::PointID>(i);
                        break;
                    }

                if (!find)
                {
                    my_positions.push_back(vertex);
                    the_tri[cpt] = static_cast<core::topology::Topology::PointID>(my_positions.size()-1);
                }
            }
            cpt++;
        }
        else if (bufferWord == "endfacet")
        {
            my_triangles.push_back(the_tri);
            cpt = 0;
        }
        else if (bufferWord == "endsolid" || bufferWord == "end")
        {
            break;
        }

        position = dataFile.tellg();
    }

    d_positions.endEdit();
    d_triangles.endEdit();
    d_normals.endEdit();

    dataFile.close();

    dmsg_info() << "done!" ;

    return true;
}

} // namespace loader

} // namespace component

} // namespace sofa

<commit_msg>fixing ascii stl loading. GRRRRR<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/core/ObjectFactory.h>
#include <SofaGeneralLoader/MeshSTLLoader.h>
#include <sofa/core/visual/VisualParams.h>

#include <sofa/helper/stl.hpp>
#include <iostream>
//#include <fstream> // we can't use iostream because the windows implementation gets confused by the mix of text and binary
#include <cstdio>
#include <sstream>
#include <string>

namespace sofa
{

namespace component
{

namespace loader
{

using namespace sofa::defaulttype;

SOFA_DECL_CLASS(MeshSTLLoader)

int MeshSTLLoaderClass = core::RegisterObject("Specific mesh loader for STL file format.")
        .add< MeshSTLLoader >()
        .addAlias("MeshStlLoader")
        ;

//Base VTK Loader
MeshSTLLoader::MeshSTLLoader() : MeshLoader()
    , _headerSize(initData(&_headerSize, 80u, "headerSize","Size of the header binary file (just before the number of facet)."))
    , _forceBinary(initData(&_forceBinary, false, "forceBinary","Force reading in binary mode. Even in first keyword of the file is solid."))
    , d_mergePositionUsingMap(initData(&d_mergePositionUsingMap, true, "mergePositionUsingMap","Since positions are duplicated in a STL, they have to be merged. Using a map to do so will temporarily duplicate memory but should be more efficient. Disable it if memory is really an issue."))
{
}

bool MeshSTLLoader::load()
{
    const char* filename = m_filename.getFullPath().c_str();

    std::ifstream file(filename);
    if (!file.good()) {
        msg_error() << "Cannot read file '" << m_filename;
        return false;
    }

    if( helper::stl::is_binary(file) || _forceBinary.getValue() ) {
        return this->readBinarySTL(filename);
    } else {
        return this->readSTL(file);
    }

}

bool MeshSTLLoader::readBinarySTL(const char *filename)
{
    dmsg_info() << "Reading binary STL file..." ;

    std::ifstream dataFile (filename, std::ios::in | std::ios::binary);

    helper::vector<sofa::defaulttype::Vector3>& my_positions = *(this->d_positions.beginWriteOnly());
    helper::vector<sofa::defaulttype::Vector3>& my_normals = *(this->d_normals.beginWriteOnly());
    helper::vector<Triangle >& my_triangles = *(this->d_triangles.beginWriteOnly());

    std::map< sofa::defaulttype::Vec3f, core::topology::Topology::index_type > my_map;
    core::topology::Topology::index_type positionCounter = 0;
    bool useMap = d_mergePositionUsingMap.getValue();

    // Skipping header file
    char buffer[256];
    dataFile.read(buffer, _headerSize.getValue());
//    sout << "Header binary file: "<< buffer << sendl;

    uint32_t nbrFacet;
    dataFile.read((char*)&nbrFacet, 4);

    my_triangles.resize( nbrFacet ); // exact size
    my_normals.resize( nbrFacet ); // exact size
    my_positions.reserve( nbrFacet * 3 ); // max size

#ifndef NDEBUG
    {
    // checking that the file is large enough to contain the given nb of facets
    // store current pos in file
    std::streampos pos = dataFile.tellg();
    // get length of file
    dataFile.seekg(0, std::ios::end);
    std::streampos length = dataFile.tellg();
    // restore pos in file
    dataFile.seekg(pos);
    // check for length
    assert( length >= _headerSize.getValue() + 4 + nbrFacet * (12 /*normal*/ + 3 * 12 /*points*/ + 2 /*attribute*/ ) );
    }
#endif

    // temporaries
    sofa::defaulttype::Vec3f vertex, normal;

    // Parsing facets
    for (uint32_t i = 0; i<nbrFacet; ++i)
    {
        Triangle& the_tri = my_triangles[i];

        // Normal:
        dataFile.read((char*)&normal[0], 4);
        dataFile.read((char*)&normal[1], 4);
        dataFile.read((char*)&normal[2], 4);
        my_normals[i] = normal;

        // Vertices:
        for (size_t j = 0; j<3; ++j)
        {
            dataFile.read((char*)&vertex[0], 4);
            dataFile.read((char*)&vertex[1], 4);
            dataFile.read((char*)&vertex[2], 4);

            if( useMap )
            {
                auto it = my_map.find( vertex );
                if( it == my_map.end() )
                {
                    the_tri[j] = positionCounter;
                    my_map[vertex] = positionCounter++;
                    my_positions.push_back(vertex);
                }
                else
                {
                    the_tri[j] = it->second;
                }
            }
            else
            {
                bool find = false;
                for (size_t k=0; k<my_positions.size(); ++k)
                    if ( (vertex[0] == my_positions[k][0]) && (vertex[1] == my_positions[k][1])  && (vertex[2] == my_positions[k][2]))
                    {
                        find = true;
                        the_tri[j] = static_cast<core::topology::Topology::PointID>(k);
                        break;
                    }

                if (!find)
                {
                    my_positions.push_back(vertex);
                    the_tri[j] = my_positions.size()-1;
                }
            }

        }

        // Attribute byte count
        uint16_t count;
        dataFile.read((char*)&count, 2);

        // Security: // checked once before reading in debug mode
//        position = dataFile.tellg();
//        if (position == length)
//            break;
    }

    this->d_positions.endEdit();
    this->d_triangles.endEdit();
    this->d_normals.endEdit();

    dmsg_info() << "done!" ;

    return true;
}

bool MeshSTLLoader::readSTL(std::ifstream& dataFile)
{
    dmsg_info() << "Reading STL file..." ;

    // Init
    std::string buffer;
    std::string name; // name of the solid, needed?

    helper::vector<sofa::defaulttype::Vector3>& my_positions = *(d_positions.beginEdit());
    helper::vector<sofa::defaulttype::Vector3>& my_normals = *(d_normals.beginEdit());
    helper::vector<Triangle >& my_triangles = *(d_triangles.beginEdit());

    std::map< sofa::defaulttype::Vec3f, core::topology::Topology::index_type > my_map;
    core::topology::Topology::index_type positionCounter = 0;
    bool useMap = d_mergePositionUsingMap.getValue();

    // get length of file:
    dataFile.seekg(0, std::ios::end);
    std::streampos length = dataFile.tellg();
    dataFile.seekg(0, std::ios::beg);

    // Reading header
    dataFile >> buffer >> name;

    Triangle the_tri;
    size_t cpt = 0;
    std::streampos position = 0;

    // Parsing facets
    while (position < length)
    {
        sofa::defaulttype::Vector3 normal, vertex;

        std::getline(dataFile, buffer);
        std::stringstream line;
        line << buffer;

        std::string bufferWord;
        line >> bufferWord;

        if (bufferWord == "facet")
        {
            line >> bufferWord >> normal[0] >> normal[1] >> normal[2];
            my_normals.push_back(normal);
        }
        else if (bufferWord == "vertex")
        {
            line >> vertex[0] >> vertex[1] >> vertex[2];

            if( useMap )
            {
                auto it = my_map.find( vertex );
                if( it == my_map.end() )
                {
                    the_tri[cpt] = positionCounter;
                    my_map[vertex] = positionCounter++;
                    my_positions.push_back(vertex);
                }
                else
                {
                    the_tri[cpt] = it->second;
                }
            }
            else
            {

                bool find = false;
                for (size_t i=0; i<my_positions.size(); ++i)
                    if ( (vertex[0] == my_positions[i][0]) && (vertex[1] == my_positions[i][1])  && (vertex[2] == my_positions[i][2]))
                    {
                        find = true;
                        the_tri[cpt] = static_cast<core::topology::Topology::PointID>(i);
                        break;
                    }

                if (!find)
                {
                    my_positions.push_back(vertex);
                    the_tri[cpt] = static_cast<core::topology::Topology::PointID>(my_positions.size()-1);
                }
            }
            cpt++;
        }
        else if (bufferWord == "endfacet")
        {
            my_triangles.push_back(the_tri);
            cpt = 0;
        }
        else if (bufferWord == "endsolid" || bufferWord == "end")
        {
            break;
        }

        position = dataFile.tellg();
    }

    d_positions.endEdit();
    d_triangles.endEdit();
    d_normals.endEdit();

    dataFile.close();

    dmsg_info() << "done!" ;

    return true;
}

} // namespace loader

} // namespace component

} // namespace sofa

<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "tcpportsgatherer.h"
#include "qtcassert.h"
#include <QFile>
#include <QStringList>
#include <QProcess>

#ifdef Q_OS_WIN
#include <QLibrary>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#endif

namespace Utils {
namespace Internal {

class TcpPortsGathererPrivate
{
public:
    TcpPortsGathererPrivate(TcpPortsGatherer::ProtocolFlags protocolFlags)
        : protocolFlags(protocolFlags) {}

    TcpPortsGatherer::ProtocolFlags protocolFlags;
    PortList usedPorts;

    void updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags);
    void updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags);
    void updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags);
};

#ifdef Q_OS_WIN
template <typename Table >
QSet<int> usedTcpPorts(ULONG (__stdcall *Func)(Table*, PULONG, BOOL))
{
    Table *table = static_cast<Table*>(malloc(sizeof(Table)));
    DWORD dwSize = sizeof(Table);

    // get the necessary size into the dwSize variable
    DWORD dwRetVal = Func(table, &dwSize, false);
    if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) {
        free(table);
        table = static_cast<Table*>(malloc(dwSize));
    }

    // get the actual data
    QSet<int> result;
    dwRetVal = Func(table, &dwSize, false);
    if (dwRetVal == NO_ERROR) {
        for (quint32 i = 0; i < table->dwNumEntries; i++) {
            quint16 port = ntohs(table->table[i].dwLocalPort);
            if (!result.contains(port))
                result.insert(port);
        }
    } else {
        qWarning() << "TcpPortsGatherer: GetTcpTable failed with" << dwRetVal;
    }

    free(table);
    return result;
}
#endif

void TcpPortsGathererPrivate::updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags)
{
#ifdef Q_OS_WIN
    QSet<int> ports;

    if (protocolFlags & TcpPortsGatherer::IPv4Protocol)
        ports.unite(usedTcpPorts<MIB_TCPTABLE>(GetTcpTable));

    //Dynamically load symbol for GetTcp6Table for systems that dont have support for IPV6,
    //eg Windows XP
    typedef ULONG (__stdcall *GetTcp6TablePtr)(PMIB_TCP6TABLE, PULONG, BOOL);
    static GetTcp6TablePtr getTcp6TablePtr = 0;

    if (!getTcp6TablePtr)
        getTcp6TablePtr = (GetTcp6TablePtr)QLibrary::resolve(QLatin1String("Iphlpapi.dll"),
                                                             "GetTcp6Table");

    if (getTcp6TablePtr && (protocolFlags & TcpPortsGatherer::IPv6Protocol))
        ports.unite(usedTcpPorts<MIB_TCP6TABLE>(getTcp6TablePtr));

    foreach (int port, ports) {
        if (!usedPorts.contains(port))
            usedPorts.addPort(port);
    }
#endif
    Q_UNUSED(protocolFlags);
}

void TcpPortsGathererPrivate::updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags)
{
    QStringList filePaths;
    if (protocolFlags & TcpPortsGatherer::IPv4Protocol)
        filePaths.append(QLatin1String("/proc/net/tcp"));
    if (protocolFlags & TcpPortsGatherer::IPv6Protocol)
        filePaths.append(QLatin1String("/proc/net/tcp6"));

    foreach (const QString &filePath, filePaths) {
        QFile file(filePath);
        if (!file.open(QFile::ReadOnly | QFile::Text)) {
            qWarning() << "TcpPortsGatherer: Cannot open file"
                       << filePath << ":" << file.errorString();
            continue;
        }

        if (file.atEnd()) // read first line describing the output
            file.readLine();

        static QRegExp pattern(QLatin1String("^\\s*" // start of line, whitespace
                                             "\\d+:\\s*" // integer, colon, space
                                             "[0-9A-Fa-f]+:" // hexadecimal number (ip), colon
                                             "([0-9A-Fa-f]+)"  // hexadecimal number (port!)
                                             ));
        while (!file.atEnd()) {
            QByteArray line = file.readLine();
            if (pattern.indexIn(line) != -1) {
                bool isNumber;
                quint16 port = pattern.cap(1).toUShort(&isNumber, 16);
                QTC_ASSERT(isNumber, continue);
                if (!usedPorts.contains(port))
                    usedPorts.addPort(port);
            } else {
                qWarning() << "TcpPortsGatherer: File" << filePath << "has unexpected format.";
                continue;
            }
        }
    }
}

// Only works with FreeBSD version of netstat like we have on Mac OS X
void TcpPortsGathererPrivate::updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags)
{
    QStringList netstatArgs;

    netstatArgs.append(QLatin1String("-a"));     // show also sockets of server processes
    netstatArgs.append(QLatin1String("-n"));     // show network addresses as numbers
    netstatArgs.append(QLatin1String("-p"));
    netstatArgs.append(QLatin1String("tcp"));
    if (protocolFlags != TcpPortsGatherer::AnyIPProcol) {
        netstatArgs.append(QLatin1String("-f")); // limit to address family
        if (protocolFlags == TcpPortsGatherer::IPv4Protocol)
            netstatArgs.append(QLatin1String("inet"));
        else
            netstatArgs.append(QLatin1String("inet6"));
    }

    QProcess netstatProcess;
    netstatProcess.start(QLatin1String("netstat"), netstatArgs);
    if (!netstatProcess.waitForFinished(30000)) {
        qWarning() << "TcpPortsGatherer: netstat did not return in time.";
        return;
    }

    QList<QByteArray> output = netstatProcess.readAllStandardOutput().split('\n');
    foreach (const QByteArray &line, output) {
        static QRegExp pattern(QLatin1String("^tcp[46]+" // "tcp", followed by "4", "6", "46"
                                             "\\s+\\d+"           // whitespace, number (Recv-Q)
                                             "\\s+\\d+"           // whitespace, number (Send-Q)
                                             "\\s+(\\S+)"));       // whitespace, Local Address
        if (pattern.indexIn(line) != -1) {
            QString localAddress = pattern.cap(1);

            // Examples of local addresses:
            // '*.56501' , '*.*' 'fe80::1%lo0.123'
            int portDelimiterPos = localAddress.lastIndexOf(".");
            if (portDelimiterPos == -1)
                continue;

            localAddress = localAddress.mid(portDelimiterPos + 1);
            bool isNumber;
            quint16 port = localAddress.toUShort(&isNumber);
            if (!isNumber)
                continue;

            if (!usedPorts.contains(port))
                usedPorts.addPort(port);
        }
    }
}

} // namespace Internal

/*!
  \class Utils::TcpPortsGatherer

  \brief Gather the list of local TCP ports already in use.

  Query the system for the list of local TCP ports already in use. This information can be used
  to select a port for use in a range.
*/

TcpPortsGatherer::TcpPortsGatherer(TcpPortsGatherer::ProtocolFlags protocolFlags)
    : d(new Internal::TcpPortsGathererPrivate(protocolFlags))
{
    update();
}

TcpPortsGatherer::~TcpPortsGatherer()
{
    delete d;
}

void TcpPortsGatherer::update()
{
    d->usedPorts = PortList();

#if defined(Q_OS_WIN)
    d->updateWin(d->protocolFlags);
#elif defined(Q_OS_LINUX)
    d->updateLinux(d->protocolFlags);
#else
    d->updateNetstat(d->protocolFlags);
#endif
}

PortList TcpPortsGatherer::usedPorts() const
{
    return d->usedPorts;
}

/*!
  Select a port out of \a freePorts that is not yet used.

  Returns the port, or 0 if no free port is available.
  */
quint16 TcpPortsGatherer::getNextFreePort(PortList *freePorts)
{
    QTC_ASSERT(freePorts, return 0);
    while (freePorts->hasMore()) {
        const int port = freePorts->getNext();
        if (!d->usedPorts.contains(port))
            return port;
    }
    return 0;
}

} // namespace Utils
<commit_msg>TcpPortsGatherer: Fix compilation with MinGW/4.6.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "tcpportsgatherer.h"
#include "qtcassert.h"
#include <QFile>
#include <QStringList>
#include <QProcess>

#ifdef Q_OS_WIN
#include <QLibrary>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#endif

#if defined(Q_OS_WIN) && defined(Q_CC_MINGW)

// Missing declarations for MinGW. This requires MinGW with gcc 4.6.
typedef enum { } MIB_TCP_STATE;

typedef struct _MIB_TCP6ROW {
    MIB_TCP_STATE State;
    IN6_ADDR LocalAddr;
    DWORD dwLocalScopeId;
    DWORD dwLocalPort;
    IN6_ADDR RemoteAddr;
    DWORD dwRemoteScopeId;
    DWORD dwRemotePort;
} MIB_TCP6ROW, *PMIB_TCP6ROW;

typedef struct _MIB_TCP6TABLE {
    DWORD dwNumEntries;
    MIB_TCP6ROW table[ANY_SIZE];
} MIB_TCP6TABLE, *PMIB_TCP6TABLE;

#endif // defined(Q_OS_WIN) && defined(Q_CC_MINGW)

namespace Utils {
namespace Internal {

class TcpPortsGathererPrivate
{
public:
    TcpPortsGathererPrivate(TcpPortsGatherer::ProtocolFlags protocolFlags)
        : protocolFlags(protocolFlags) {}

    TcpPortsGatherer::ProtocolFlags protocolFlags;
    PortList usedPorts;

    void updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags);
    void updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags);
    void updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags);
};

#ifdef Q_OS_WIN
template <typename Table >
QSet<int> usedTcpPorts(ULONG (__stdcall *Func)(Table*, PULONG, BOOL))
{
    Table *table = static_cast<Table*>(malloc(sizeof(Table)));
    DWORD dwSize = sizeof(Table);

    // get the necessary size into the dwSize variable
    DWORD dwRetVal = Func(table, &dwSize, false);
    if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) {
        free(table);
        table = static_cast<Table*>(malloc(dwSize));
    }

    // get the actual data
    QSet<int> result;
    dwRetVal = Func(table, &dwSize, false);
    if (dwRetVal == NO_ERROR) {
        for (quint32 i = 0; i < table->dwNumEntries; i++) {
            quint16 port = ntohs(table->table[i].dwLocalPort);
            if (!result.contains(port))
                result.insert(port);
        }
    } else {
        qWarning() << "TcpPortsGatherer: GetTcpTable failed with" << dwRetVal;
    }

    free(table);
    return result;
}
#endif

void TcpPortsGathererPrivate::updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags)
{
#ifdef Q_OS_WIN
    QSet<int> ports;

    if (protocolFlags & TcpPortsGatherer::IPv4Protocol)
        ports.unite(usedTcpPorts<MIB_TCPTABLE>(GetTcpTable));

    //Dynamically load symbol for GetTcp6Table for systems that dont have support for IPV6,
    //eg Windows XP
    typedef ULONG (__stdcall *GetTcp6TablePtr)(PMIB_TCP6TABLE, PULONG, BOOL);
    static GetTcp6TablePtr getTcp6TablePtr = 0;

    if (!getTcp6TablePtr)
        getTcp6TablePtr = (GetTcp6TablePtr)QLibrary::resolve(QLatin1String("Iphlpapi.dll"),
                                                             "GetTcp6Table");

    if (getTcp6TablePtr && (protocolFlags & TcpPortsGatherer::IPv6Protocol))
        ports.unite(usedTcpPorts<MIB_TCP6TABLE>(getTcp6TablePtr));

    foreach (int port, ports) {
        if (!usedPorts.contains(port))
            usedPorts.addPort(port);
    }
#endif
    Q_UNUSED(protocolFlags);
}

void TcpPortsGathererPrivate::updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags)
{
    QStringList filePaths;
    if (protocolFlags & TcpPortsGatherer::IPv4Protocol)
        filePaths.append(QLatin1String("/proc/net/tcp"));
    if (protocolFlags & TcpPortsGatherer::IPv6Protocol)
        filePaths.append(QLatin1String("/proc/net/tcp6"));

    foreach (const QString &filePath, filePaths) {
        QFile file(filePath);
        if (!file.open(QFile::ReadOnly | QFile::Text)) {
            qWarning() << "TcpPortsGatherer: Cannot open file"
                       << filePath << ":" << file.errorString();
            continue;
        }

        if (file.atEnd()) // read first line describing the output
            file.readLine();

        static QRegExp pattern(QLatin1String("^\\s*" // start of line, whitespace
                                             "\\d+:\\s*" // integer, colon, space
                                             "[0-9A-Fa-f]+:" // hexadecimal number (ip), colon
                                             "([0-9A-Fa-f]+)"  // hexadecimal number (port!)
                                             ));
        while (!file.atEnd()) {
            QByteArray line = file.readLine();
            if (pattern.indexIn(line) != -1) {
                bool isNumber;
                quint16 port = pattern.cap(1).toUShort(&isNumber, 16);
                QTC_ASSERT(isNumber, continue);
                if (!usedPorts.contains(port))
                    usedPorts.addPort(port);
            } else {
                qWarning() << "TcpPortsGatherer: File" << filePath << "has unexpected format.";
                continue;
            }
        }
    }
}

// Only works with FreeBSD version of netstat like we have on Mac OS X
void TcpPortsGathererPrivate::updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags)
{
    QStringList netstatArgs;

    netstatArgs.append(QLatin1String("-a"));     // show also sockets of server processes
    netstatArgs.append(QLatin1String("-n"));     // show network addresses as numbers
    netstatArgs.append(QLatin1String("-p"));
    netstatArgs.append(QLatin1String("tcp"));
    if (protocolFlags != TcpPortsGatherer::AnyIPProcol) {
        netstatArgs.append(QLatin1String("-f")); // limit to address family
        if (protocolFlags == TcpPortsGatherer::IPv4Protocol)
            netstatArgs.append(QLatin1String("inet"));
        else
            netstatArgs.append(QLatin1String("inet6"));
    }

    QProcess netstatProcess;
    netstatProcess.start(QLatin1String("netstat"), netstatArgs);
    if (!netstatProcess.waitForFinished(30000)) {
        qWarning() << "TcpPortsGatherer: netstat did not return in time.";
        return;
    }

    QList<QByteArray> output = netstatProcess.readAllStandardOutput().split('\n');
    foreach (const QByteArray &line, output) {
        static QRegExp pattern(QLatin1String("^tcp[46]+" // "tcp", followed by "4", "6", "46"
                                             "\\s+\\d+"           // whitespace, number (Recv-Q)
                                             "\\s+\\d+"           // whitespace, number (Send-Q)
                                             "\\s+(\\S+)"));       // whitespace, Local Address
        if (pattern.indexIn(line) != -1) {
            QString localAddress = pattern.cap(1);

            // Examples of local addresses:
            // '*.56501' , '*.*' 'fe80::1%lo0.123'
            int portDelimiterPos = localAddress.lastIndexOf(".");
            if (portDelimiterPos == -1)
                continue;

            localAddress = localAddress.mid(portDelimiterPos + 1);
            bool isNumber;
            quint16 port = localAddress.toUShort(&isNumber);
            if (!isNumber)
                continue;

            if (!usedPorts.contains(port))
                usedPorts.addPort(port);
        }
    }
}

} // namespace Internal

/*!
  \class Utils::TcpPortsGatherer

  \brief Gather the list of local TCP ports already in use.

  Query the system for the list of local TCP ports already in use. This information can be used
  to select a port for use in a range.
*/

TcpPortsGatherer::TcpPortsGatherer(TcpPortsGatherer::ProtocolFlags protocolFlags)
    : d(new Internal::TcpPortsGathererPrivate(protocolFlags))
{
    update();
}

TcpPortsGatherer::~TcpPortsGatherer()
{
    delete d;
}

void TcpPortsGatherer::update()
{
    d->usedPorts = PortList();

#if defined(Q_OS_WIN)
    d->updateWin(d->protocolFlags);
#elif defined(Q_OS_LINUX)
    d->updateLinux(d->protocolFlags);
#else
    d->updateNetstat(d->protocolFlags);
#endif
}

PortList TcpPortsGatherer::usedPorts() const
{
    return d->usedPorts;
}

/*!
  Select a port out of \a freePorts that is not yet used.

  Returns the port, or 0 if no free port is available.
  */
quint16 TcpPortsGatherer::getNextFreePort(PortList *freePorts)
{
    QTC_ASSERT(freePorts, return 0);
    while (freePorts->hasMore()) {
        const int port = freePorts->getNext();
        if (!d->usedPorts.contains(port))
            return port;
    }
    return 0;
}

} // namespace Utils
<|endoftext|>


<commit_before>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_1.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
//  Mat edges;
  for (; ;) {
    Mat mask;
    Mat frame, hsv;
    cap >> frame; // get a new frame from camera

    resize(frame, frame, Size(), .2, .2);
    cvtColor(frame, hsv, CV_BGR2HSV);

    double minH = 30;
    double minS = 0;
    double minV = 240;
    double maxH = 80;
    double maxS = 70;
    double maxV = 255;

    cv::Scalar lower(minH, minS, minV);
    cv::Scalar upper(maxH, maxS, maxV);
    cv::inRange(hsv, lower, upper, mask);

//    bitwise_and(frame, frame, frame, mask);

    vector <Vec4i> lines;
    HoughLinesP(mask, lines, 1, CV_PI / 180.0, 10, 100, 10);

    printf("Adding in %d lines\n", (int) lines.size());
    for (size_t i = 0; i < lines.size(); i++) {
      Vec4i l = lines[i];
      line(frame, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
      // break;
    }
//    if (lines.size() < 1) continue;

    imshow("edges", frame);
    if (waitKey(30) >= 0) break;

  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<commit_msg>size changes<commit_after>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_1.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
//  Mat edges;
  for (; ;) {
    Mat mask;
    Mat frame, hsv;
    cap >> frame; // get a new frame from camera

    resize(frame, frame, Size(), .2, .2);
    cvtColor(frame, hsv, CV_BGR2HSV);

    double minH = 30;
    double minS = 0;
    double minV = 240;
    double maxH = 80;
    double maxS = 70;
    double maxV = 255;

    cv::Scalar lower(minH, minS, minV);
    cv::Scalar upper(maxH, maxS, maxV);
    cv::inRange(hsv, lower, upper, mask);

//    bitwise_and(frame, frame, frame, mask);

    vector <Vec4i> lines;
    HoughLinesP(mask, lines, 1, CV_PI / 180.0, 10, 100, 10);

    printf("Adding in %d lines\n", (int) lines.size());
    for (size_t i = 0; i < lines.size(); i++) {
      Vec4i l = lines[i];
      line(frame, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, CV_AA);
      // break;
    }
//    if (lines.size() < 1) continue;

    imshow("edges", frame);
    if (waitKey(30) >= 0) break;

  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<|endoftext|>


<commit_before>//*******************************************************************
// Copyright (C) 2001 ImageLinks Inc.  All rights reserved.
//
// License:  See top level LICENSE.txt file.
//
// Author:  Oscar Kramer (ossim port by D. Burken)
//
// Description:
//
// Contains definition of class ossimXmlAttribute.
//
//*****************************************************************************
// $Id: ossimXmlAttribute.cpp 23503 2015-09-08 07:07:51Z rashadkm $

#include <iostream>
#include <sstream>

#include <ossim/base/ossimXmlAttribute.h>
#include <ossim/base/ossimNotifyContext.h>

RTTI_DEF2(ossimXmlAttribute, "ossimXmlAttribute", ossimObject, ossimErrorStatusInterface)

static std::istream& xmlskipws(std::istream& in)
{
   int c = in.peek();
   while((!in.fail())&&
         ((c == ' ') ||
          (c == '\t') ||
          (c == '\n')||
          (c == '\r')))
   {
      in.ignore(1);
      c = in.peek();
   }

   return in;
}

ossimXmlAttribute::ossimXmlAttribute(ossimString& spec)
{
   std::stringstream in(spec);

   read(in);
}

ossimXmlAttribute::ossimXmlAttribute(const ossimXmlAttribute& src)
   :theName(src.theName),
    theValue(src.theValue)
{
}

bool ossimXmlAttribute::read(std::istream& in)
{
   xmlskipws(in);
   if(in.fail()) return false;
   if(readName(in))
   {
      xmlskipws(in);
      if((in.peek() != '=')||
         (in.fail()))
      {
         setErrorStatus();
         return false;
      }
      in.ignore(1);
      if(readValue(in))
      {
         return true;
      }
      else
      {
         setErrorStatus();
         return false;
      }
   }
   return false;

#if 0
   //
   // Pull out name:
   //
   theName = spec.before('=');
   theName = theName.trim();
   if (theName.empty())
   {
      ossimNotify(ossimNotifyLevel_FATAL) << "ossimXmlAttribute::ossimXmlAttribute \n"
                                           << "Bad attribute format encountered near:\n\""<< spec<<"\"\n"
                                           << "Parsing aborted...\n";
      setErrorStatus();

      return;
   }
   spec = spec.after('=');

   //***
   // Read value:
   //***
   char quote_char = spec[0];
   spec = spec.after(quote_char);  // after first quote
   theValue = spec.before(quote_char); // before second quote

   //
   // Reposition attribute specification to the start of next attribute or end
   // of tag:
   //
   spec = spec.after(quote_char);  // after second quote
   ossimString next_entry ("-?[+0-9A-Za-z<>]+");
   spec = spec.fromRegExp(next_entry.c_str());
#endif
}

ossimXmlAttribute::~ossimXmlAttribute()
{
}

ossimXmlAttribute::ossimXmlAttribute()
{
}

ossimXmlAttribute::ossimXmlAttribute(const ossimString& name,
                                     const ossimString& value)
{
   setNameValue(name, value);
}

const ossimString& ossimXmlAttribute::getName()  const
{
   return theName;
}

const ossimString& ossimXmlAttribute::getValue() const
{
   return theValue;
}

void ossimXmlAttribute::setNameValue(const ossimString& name,
                                     const ossimString& value)
{
   theName  = name;
   theValue = value;
}

void ossimXmlAttribute::setName(const ossimString& name)
{
   theName = name;
}

void ossimXmlAttribute::setValue(const ossimString& value)
{
   theValue = value;
}

std::ostream& operator << (std::ostream& os, const ossimXmlAttribute* xml_attr)
{
   os << " " << xml_attr->theName << "=\"" << xml_attr->theValue << "\"";

   return os;
}

bool ossimXmlAttribute::readName(std::istream& in)
{
   xmlskipws(in);
   theName = "";
   char c = in.peek();
   while((c != ' ')&&
         (c != '\n')&&
	 (c != '\r')&&
         (c != '\t')&&
         (c != '=')&&
         (c != '<')&&
         (c != '/')&&
         (c != '>')&&
         (!in.fail()))
   {
      theName += (char)in.get();
      c = in.peek();
   }

   return ((!in.fail())&&
           (theName != ""));
}

bool ossimXmlAttribute::readValue(std::istream& in)
{
   xmlskipws(in);
   if(in.fail()) return false;
   theValue = "";
   char c = in.peek();
   bool done = false;
	char startQuote = '\0';
   if((c == '\'')||
      (c == '"'))
   {
      startQuote = c;
      theValue += in.get();
    while(!done&&!in.fail())
      {
         c = in.peek();
         if(c==startQuote)
         {
            theValue += c;
            done = true;
            in.ignore(1);
         }
         else if(c == '\n')
         {
            done = true;
         }
         else
         {
            theValue += in.get();
         }
      }
   }

   bool is_empty = false;
   //then this could be empty with two qoutes
    if(theValue.size() == 2 && theValue[0] == startQuote && theValue[1] == startQuote)
    {
       theValue = "";
       is_empty = true;
    }
   if(theValue != "")
   {
      std::string::iterator startIter = theValue.begin();
      std::string::iterator endIter   = theValue.end();
      --endIter;
      if(*startIter == startQuote)
      {
         ++startIter;
      }
      else
      {
         return false;
         setErrorStatus();
      }
      if(*endIter != startQuote)
      {
         return false;
         setErrorStatus();
      }
      theValue = ossimString(startIter, endIter);
   }
   return ((!in.bad())&& (is_empty || theValue !=""));
}
<commit_msg>build fails on msvc. error C2999<commit_after>//*******************************************************************
// Copyright (C) 2001 ImageLinks Inc.  All rights reserved.
//
// License:  See top level LICENSE.txt file.
//
// Author:  Oscar Kramer (ossim port by D. Burken)
//
// Description:
//
// Contains definition of class ossimXmlAttribute.
//
//*****************************************************************************
// $Id: ossimXmlAttribute.cpp 23503 2015-09-08 07:07:51Z rashadkm $

#include <iostream>
#include <sstream>

#include <ossim/base/ossimXmlAttribute.h>
#include <ossim/base/ossimNotifyContext.h>

RTTI_DEF2(ossimXmlAttribute, "ossimXmlAttribute", ossimObject, ossimErrorStatusInterface)

static std::istream& xmlskipws(std::istream& in)
{
   int c = in.peek();
   while((!in.fail())&&
         ((c == ' ') ||
          (c == '\t') ||
          (c == '\n')||
          (c == '\r')))
   {
      in.ignore(1);
      c = in.peek();
   }

   return in;
}

ossimXmlAttribute::ossimXmlAttribute(ossimString& spec)
{
   std::stringstream in(spec);

   read(in);
}

ossimXmlAttribute::ossimXmlAttribute(const ossimXmlAttribute& src)
   :theName(src.theName),
    theValue(src.theValue)
{
}

bool ossimXmlAttribute::read(std::istream& in)
{
   xmlskipws(in);
   if(in.fail()) return false;
   if(readName(in))
   {
      xmlskipws(in);
      if((in.peek() != '=')||
         (in.fail()))
      {
         setErrorStatus();
         return false;
      }
      in.ignore(1);
      if(readValue(in))
      {
         return true;
      }
      else
      {
         setErrorStatus();
         return false;
      }
   }
   return false;

#if 0
   //
   // Pull out name:
   //
   theName = spec.before('=');
   theName = theName.trim();
   if (theName.empty())
   {
      ossimNotify(ossimNotifyLevel_FATAL) << "ossimXmlAttribute::ossimXmlAttribute \n"
                                           << "Bad attribute format encountered near:\n\""<< spec<<"\"\n"
                                           << "Parsing aborted...\n";
      setErrorStatus();

      return;
   }
   spec = spec.after('=');

   //***
   // Read value:
   //***
   char quote_char = spec[0];
   spec = spec.after(quote_char);  // after first quote
   theValue = spec.before(quote_char); // before second quote

   //
   // Reposition attribute specification to the start of next attribute or end
   // of tag:
   //
   spec = spec.after(quote_char);  // after second quote
   ossimString next_entry ("-?[+0-9A-Za-z<>]+");
   spec = spec.fromRegExp(next_entry.c_str());
#endif
}

ossimXmlAttribute::~ossimXmlAttribute()
{
}

ossimXmlAttribute::ossimXmlAttribute()
{
}

ossimXmlAttribute::ossimXmlAttribute(const ossimString& name,
                                     const ossimString& value)
{
   setNameValue(name, value);
}

const ossimString& ossimXmlAttribute::getName()  const
{
   return theName;
}

const ossimString& ossimXmlAttribute::getValue() const
{
   return theValue;
}

void ossimXmlAttribute::setNameValue(const ossimString& name,
                                     const ossimString& value)
{
   theName  = name;
   theValue = value;
}

void ossimXmlAttribute::setName(const ossimString& name)
{
   theName = name;
}

void ossimXmlAttribute::setValue(const ossimString& value)
{
   theValue = value;
}

std::ostream& operator << (std::ostream& os, const ossimXmlAttribute* xml_attr)
{
   os << " " << xml_attr->theName << "=\"" << xml_attr->theValue << "\"";

   return os;
}

bool ossimXmlAttribute::readName(std::istream& in)
{
   xmlskipws(in);
   theName = "";
   char c = in.peek();
   while((c != ' ')&&
         (c != '\n')&&
	 (c != '\r')&&
         (c != '\t')&&
         (c != '=')&&
         (c != '<')&&
         (c != '/')&&
         (c != '>')&&
         (!in.fail()))
   {
      theName += (char)in.get();
      c = in.peek();
   }

   return ((!in.fail())&&
           (theName != ""));
}

bool ossimXmlAttribute::readValue(std::istream& in)
{
   xmlskipws(in);
   if(in.fail()) return false;
   theValue = "";
   char c = in.peek();
   bool done = false;
	char startQuote = '\0';
   if((c == '\'')||
      (c == '"'))
   {
      startQuote = c;
      theValue += in.get();
    while(!done&&!in.fail())
      {
         c = in.peek();
         if(c==startQuote)
         {
            theValue += c;
            done = true;
            in.ignore(1);
         }
         else if(c == '\n')
         {
            done = true;
         }
         else
         {
            theValue += in.get();
         }
      }
   }

   bool is_empty = false;
   //then this could be empty with two qoutes
   std::string::size_type p = 0;
   //then this could be empty with two qoutes
    if(theValue.size() == 2 && theValue[p] == startQuote && theValue[p+1] == startQuote)
    {
       theValue = "";
       is_empty = true;
    }
   if(theValue != "")
   {
      std::string::iterator startIter = theValue.begin();
      std::string::iterator endIter   = theValue.end();
      --endIter;
      if(*startIter == startQuote)
      {
         ++startIter;
      }
      else
      {
         return false;
         setErrorStatus();
      }
      if(*endIter != startQuote)
      {
         return false;
         setErrorStatus();
      }
      theValue = ossimString(startIter, endIter);
   }
   return ((!in.bad())&& (is_empty || theValue !=""));
}
<|endoftext|>